|
81 | 81 | * [Override operator description](#override-operator-description) |
82 | 82 | * [Override operand formatting](#override-operand-formatting) |
83 | 83 | * [Localization](#localization) |
84 | | - * [Concrete phrases and grammatical categories](#concrete-phrases-and-grammatical-categories) |
| 84 | + * [Grammatical categories and concrete phrases](#grammatical-categories-and-concrete-phrases) |
85 | 85 | * [Translators](#translators) |
86 | | - * [Translator repository](#translator-repository) |
| 86 | + * [Repository of translators](#repository-of-translators) |
87 | 87 | * [Adding new locale](#adding-new-locale) |
88 | 88 | * [Building and installation](#building-and-installation) |
89 | 89 | * [Supported platforms and compilers](#supported-platforms-and-compilers) |
@@ -123,18 +123,12 @@ Customizable validation implementer. Adapter performs actual validation when the |
123 | 123 | ##### *Aggregation* |
124 | 124 | Combination of validating [operators](#operator) or other [validators](#validator) that make up a compound [validator](#validator). There are logical aggregations such as _AND_, _OR_, _NOT_ and [element](#element) aggregations such as _ANY_, _ALL_. |
125 | 125 |
|
126 | | -##### *Concrete phrase* |
127 | | -Immutable string that will be used in final [report](#report). |
128 | | - |
129 | 126 | ##### *Element* |
130 | 127 | A special type of [member](#member) that points to an element of container when the [object](#object) is a container. |
131 | 128 |
|
132 | 129 | ##### *Formatter* |
133 | 130 | Customizable implementer of [reports](#report) formatting. See [formatters](#formatters) section. |
134 | 131 |
|
135 | | -##### *Grammatical category* |
136 | | -A grammatical category is a property of items within the grammar of a language (see https://en.wikipedia.org/wiki/Grammatical_category). In some languages different grammatical categories of some words can affect the forms of the successive words in a phrase. In this library grammatical categories are used for more natural [reports](#report) construction. |
137 | | - |
138 | 132 | ##### *Member* |
139 | 133 | An [element](#element) or a [property](#property) of [object](#object) the validation must be applied to. Members can be either direct (single level depth) or nested (multi level depth). |
140 | 134 |
|
@@ -2070,14 +2064,126 @@ return 0; |
2070 | 2064 |
|
2071 | 2065 | ### Localization |
2072 | 2066 |
|
2073 | | -#### Concrete phrases and grammatical categories |
| 2067 | +[Reports](#report) can be translated either with the external translation tools or with the localization tools of `cpp-validator` library. |
| 2068 | + |
| 2069 | +External translation tools can be used only for translation of the whole final [report](#report). In order to translate the whole [report](#report) with the external translation tools one must give desired translation of the [report](#report) as a [hint to validator](#Override-the-whole-report). |
| 2070 | + |
| 2071 | +In `cpp-validator` a [report](#report) is usually constructed by a [formatter](#formatter) dynamically *on-the-fly* from the parts prepared with [partial formatters](#formatters). Thus, with `cpp-validator` library the final [report](#report) can not be translated in advance. Instead, only parts from [partial formatters](#formatters) can be translated in advance that will be dynamically [joined](#strings-order-and-presentation) into the final [report](#report) later. |
| 2072 | + |
| 2073 | +#### Grammatical categories and concrete phrases |
| 2074 | + |
| 2075 | +A *grammatical category* is a property of items within the grammar of a language (see https://en.wikipedia.org/wiki/Grammatical_category). In some languages different *grammatical categories* of some words can affect the forms of the successive words in a phrase. For example the forms of *go* word are different in phrases *I go*, *they go*, *she **goes***. |
| 2076 | + |
| 2077 | +In `cpp-validator` library *grammatical categories* are used for more natural [reports](#report) construction. When results from the [partial formatters](#formatters) are being [joined](#strings-order-and-presentation) the results of the successive [partial formatters](#formatters) can depend on *grammatical categories* of the previous results. |
| 2078 | + |
| 2079 | +`concrete_phrase` class is used to combine the string result of a [partial formatter](#formatters) and *grammatical categories* of that string actual for the current locale. |
| 2080 | + |
| 2081 | +*Grammatical categories* are used by [translators](#translator) to select which translations must be used in certain cases. Result of a single translation is returned as `concrete_phrase`. String value of the `concrete_phrase` will be used in the final [report](#report). *Grammatical categories* of the `concrete_phrase` will be used by [translator](#translator) of the next [partial formatter](#formatters) to select corresponding translation. |
2074 | 2082 |
|
2075 | 2083 | #### Translators |
2076 | 2084 |
|
2077 | | -#### Translator repository |
| 2085 | +Translators are used by [partial formatters](#formatters) to translate partial string results. Base `translator` class is defined in `validator/reporting/translator.hpp` header file. |
| 2086 | + |
| 2087 | +To construct a [formatter](#formatter) in which all [partial formatters](#formatters) use the same translator use `make_formatter(translator_instance)` or `make_formatter(translator_instance,std::true_type())` helpers. Besides, different translators can be used in different [partial formatters](#formatters). See corresponding `make_translated_member_names()`, `make_translated_strings()` and `make_translated_operand_formatter()` helpers. |
| 2088 | + |
| 2089 | +##### Translator with grammatical categories |
| 2090 | + |
| 2091 | +`phrase_translator` defined in `validator/reporting/phrase_translator.hpp` can be used as a base class for *grammatical categories* aware translators. Each string in `phrase_translator` can be bound to two types of grammatical categories: |
| 2092 | +- *grammatical categories* of *preceding phrase* that should be use to select *current phrase*; |
| 2093 | +- *grammatical categories* of *current phrase* that should be used for translation of the *successive phrase*. |
| 2094 | + |
| 2095 | +*Grammatical categories* of the latter type are stored within current `concrete_phrase`. *Grammatical categories* of the former type are used as selectors of the most suitable phrase translation of given string in the `phrase_translator`. Translator will select the phrase with the maximum number of matching grammatical categories of the former type. |
| 2096 | + |
| 2097 | +#### Repository of translators |
| 2098 | + |
| 2099 | +*Translator repository* is a repository of [translators](#translator) mapped to names of locales. `translator_repository` is defined in `validator/reporting/translator_repository.hpp` header file. |
| 2100 | + |
| 2101 | +To construct a [formatter](#formatter) in which all [partial formatters](#formatters) select translator for locale from the same *translator repository* use `make_formatter(translator_repository_instance,current_locale)` or `make_formatter(translator_repository_instance,current_locale,std::true_type())` helpers. Besides, different *translator repositories* and locales can be used in different [partial formatters](#formatters). See corresponding `make_translated_member_names()`, `make_translated_strings()` and `make_translated_operand_formatter()` helpers. |
| 2102 | + |
| 2103 | +A name of locale can be either in more generic form like "en" or in more specific form like "en_US.UTF-8". When looking for a [translator](#translator) the *repository* will first try to use the most specific name of locale, and if that is not found then the *repository* will try to use further less specific names down to the name of language only. If still no [translator](#translator) is found then the default translator will be used. A [translator](#translator) should be added to the repository with the full list of all forms of locale names this [translator](#translator) is suitable for. See example below. |
| 2104 | + |
| 2105 | +```cpp |
| 2106 | +const auto& translator_en_us=validator_translator_sample(); |
| 2107 | +phrase_translator translator_en_gb; |
| 2108 | + |
| 2109 | +translator_repository rep; |
| 2110 | + |
| 2111 | +// translator_en_us will be used for all "en_US" locales as well as for generic "en" language |
| 2112 | +rep.add_translator(translator_en_us,{"en","en_US","en_US.UTF-8"}); |
| 2113 | +// translator_en_gb will be used for all "en_GB" locales but for the generic "en" language the translator_en_us will be used |
| 2114 | +rep.add_translator(translator_en_gb,{"en_GB","en_GB.UTF-8"}); |
| 2115 | + |
| 2116 | +auto locale1="en_US"; |
| 2117 | +auto formatter_for_locale1=make_formatter(rep,locale1); |
| 2118 | +// formatter_for_locale1 will use translator_en_us |
| 2119 | + |
| 2120 | +auto locale2="en_GB"; |
| 2121 | +auto formatter_for_locale2=make_formatter(rep,locale2); |
| 2122 | +// formatter_for_locale2 will use translator_en_gb |
| 2123 | + |
| 2124 | +auto locale3="en"; |
| 2125 | +auto formatter_for_locale3=make_formatter(rep,locale3); |
| 2126 | +// formatter_for_locale3 will use translator_en_us |
| 2127 | +``` |
2078 | 2128 |
|
2079 | 2129 | #### Adding new locale |
2080 | 2130 |
|
| 2131 | +To add a new locale the `phrase_translator` for that locale must be filled. |
| 2132 | +
|
| 2133 | +As a sample of translator of phrases defined in `cpp-validator` library the `validator_translator_sample()` helper can be used which is defined in `validator/reporting/locale/sample_locale.hpp`. To add new language or locale copy that file, rename `validator_translator_sample()` to something like `translator_of_<locale_name>` (e.g. `translator_of_de`) and replace its phrases with the translation of the phrases for target locale. |
| 2134 | +
|
| 2135 | +If translation of a phrase depends on *grammatical categories* of the previous phrase then add translation with taking into account that dependency as follows: |
| 2136 | +```cpp |
| 2137 | +m[original]={ |
| 2138 | + {"default translation"}, |
| 2139 | + {"translation for grammatical category 1", grammatical_category1}, |
| 2140 | + {"translation for combination of grammatical category 1 and grammatical category 2", grammatical_category1, grammatical_category2} |
| 2141 | + }; |
| 2142 | +``` |
| 2143 | +See example for value and plural values: |
| 2144 | +```cpp |
| 2145 | +m[value.name()]={ |
| 2146 | + {"value"}, |
| 2147 | + {"values",grammar::plural} // use "values" translation if preceding grammatical category is grammar::plural |
| 2148 | + }; |
| 2149 | +``` |
| 2150 | +
|
| 2151 | +If translation of successive phrase can depend on *grammatical categories* of the current translated phrase then translation must be added as follows: |
| 2152 | +```cpp |
| 2153 | +m[original]={ |
| 2154 | + {{"default translation",grammatical_category_to_use_for_next_phrase}}, |
| 2155 | + {{"translation for grammatical_category_to_select_current_translation", grammatical_category_to_use_for_next_phrase}, grammatical_category_to_select_current_translation}, |
| 2156 | + { |
| 2157 | + { |
| 2158 | + "translation for combination of grammatical_category_to_select_current_translation1 and grammatical_category_to_select_current_translation2", |
| 2159 | + grammatical_category_to_use_for_next_phrase3, grammatical_category_to_use_for_next_phrase4 |
| 2160 | + }, |
| 2161 | + grammatical_category_to_select_current_translation1, |
| 2162 | + grammatical_category_to_select_current_translation2 |
| 2163 | + } |
| 2164 | + }; |
| 2165 | +``` |
| 2166 | + |
| 2167 | +See example for plural values: |
| 2168 | +```cpp |
| 2169 | +m["values"]={ |
| 2170 | + {{"values",grammar::plural}} // use this grammatical category grammar::plural for next phrase |
| 2171 | + }; |
| 2172 | +``` |
| 2173 | +
|
| 2174 | +See example for value and plural values: |
| 2175 | +```cpp |
| 2176 | +m["value"]={ |
| 2177 | + {"value"} |
| 2178 | + { |
| 2179 | + {"values",grammar::plural}, // use grammatical category grammar::plural for next phrase |
| 2180 | + grammar::plural // use "values" translation if preceding grammatical category is grammar::plural |
| 2181 | + } |
| 2182 | + }; |
| 2183 | +``` |
| 2184 | + |
| 2185 | +Another example of custom locale can be found in `validator/reporting/locale/ru.hpp` that implements translations for Russian locale. |
| 2186 | + |
2081 | 2187 | # Building and installation |
2082 | 2188 |
|
2083 | 2189 | `cpp-validator` is a header-only library, so no special library building is required. Still, some extra configuration may be required when using the library. |
|
0 commit comments