This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
en:devel:cbtranslation [2017/07/06 19:42] joebordes |
en:devel:cbtranslation [2018/12/27 12:23] (current) joebordes [cbtranslation::get()] |
||
---|---|---|---|
Line 5: | Line 5: | ||
*add strings to other modules with no code changes | *add strings to other modules with no code changes | ||
*more control of labels: avoid duplicates | *more control of labels: avoid duplicates | ||
- | *I/E | + | *Import/Export |
- | *all module advantages: mass edit | + | *all module advantages: mass edit, deduplication |
*modify any label easily | *modify any label easily | ||
*easier to translate: external tools | *easier to translate: external tools | ||
*correct functionality of picklist search | *correct functionality of picklist search | ||
*possibility to translate values on modules, not just labels | *possibility to translate values on modules, not just labels | ||
+ | *Support for using Accept-Language header when fetching required language: [[https://github.com/tsolucio/corebos/blob/master/modules/cbtranslation/cbtranslation.php#L178|getLanguage]] | ||
+ | *Support for contextual and plural translations with full sprintf syntax (see syntax below) | ||
+ | *Full support for getting plural cases in 144 languages based on http://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html?id=l10n/pluralforms | ||
+ | *Full backward compatibility | ||
=====Cons===== | =====Cons===== | ||
Line 18: | Line 22: | ||
*modifying and adding strings is harder: cbupdater? | *modifying and adding strings is harder: cbupdater? | ||
- | =====Guide===== | ||
- | This update contains : | + | =====Accept-Language Header===== |
- | *Support for using Accept-Language header when fetching required language | + | [[https://github.com/tsolucio/corebos/blob/master/modules/cbtranslation/cbtranslation.php#L178|cbTranslation::getLanguage()]] |
- | *Support for contextual and plural translations (see syntax below) | + | |
- | *Full set of utilities functions for translating with ease in each case and with full sprintf syntax support | + | |
- | *Full support for getting plural cases in 144 languages based on http://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html?id=l10n/pluralforms | + | |
- | *Full backward compatibility for letting time to update each layout | + | |
- | *Fallback to main vtiger translation file in nothing found in module translation file | + | |
- | *Very few and minor modifications | + | |
+ | Will first try to find a user chosen locale in the user settings. | ||
- | ====Accept-Language Header==== | + | If none found, it will next try to use the Accept-Language header provided by the browser. This is especially useful in the login screen for multilingual users. |
- | Will first try to find a user choosen locale in the user settings. | + | Finally, it will fallback to the global configuration |
- | If none found, it will now try to use the Accept-Language header provided by the browser. It's especially useful in login screen for multilingual users. | + | =====Contextual and plural translations===== |
- | Finally, it will fallback to global configuration | + | ====Context translation==== |
- | ====Contextual and plural translations==== | ||
- | |||
- | ===Context translation=== | ||
The use of context string lets tuning translation in special cases, e.g. taking care of gender. | The use of context string lets tuning translation in special cases, e.g. taking care of gender. | ||
- | ===Plural translations=== | + | ====Plural translations==== |
- | Many languages have differents ways of taking plurals in account, from none to 6 plural forms. | + | |
- | ===Utilities functions for translations=== | + | Many languages have different ways of taking plurals into account, from none to 6 plural forms. |
- | The basic one is <wrap hi>__(KEY_NAME)</wrap> that will return the value of KEY_NAME taken in main translations file. | + | |
- | If you use m (<wrap hi>__m(KEY_NAME, MODULE_NAME)</wrap>), it will return the value of KEY_NAME taken the module translations file (MODULE_NAME.php). | + | ====cbtranslation::get()==== |
- | If you use x (<wrap hi>__x(KEY_NAME, CONTEXT_STRING)</wrap>), it will return the value of KEY_NAME associated to the given CONTEXT_STRING. | + | The [[https://github.com/tsolucio/corebos/blob/master/modules/cbtranslation/cbtranslation.php#L225|cbtranslation::get()]] method has full support for context and plurals, among other features. |
- | If you use n (<wrap hi>__n(KEY_NAME, COUNT)</wrap>), it will return the value of KEY_NAME linked to the right plural form for COUNT items. | + | The basic usage is <wrap hi>cbtranslation::get('friend')</wrap> that will return the value of 'friend' taken from the module cbtranslation values (equivalent to the previous main translation file in include/language). |
- | You can mix all of these options : <wrap hi>__mx, __mn, __xn, __mxn</wrap> | + | Next we can pass in the module as we did before with getTranslatedString, <wrap hi>cbtranslation::get('friend','Users')</wrap>, which will return the value of 'friend' taken from the Users module translations entries in the database. |
- | For instance, the actual getTranslatedString function is the same than __m(KEY_NAME, $MODULE). | + | The third parameter is an array with a set of options for the translation. |
- | ===Taking care of context and plural in translations files=== | + | * language => <String> language to translate against, if not set $current_language will be used |
- | The pattern used for key naming is the same than JS library I18next (see https://www.i18next.com/plurals.html and https://www.i18next.com/context.html). | + | * context => <String> label modifier for specific translation contexts, like gender. The context is simply added after key name separated by an underscore. |
+ | * count => <Integer> label modifier for plurals. Plurals are written following gettext format. For a language with 2 plural forms, you keep KEY_NAME for singular and KEY_NAME_PLURAL for plural. For a language with 3 or more plural forms, it will be KEY_NAME_0, KEY_NAME_1, ..., KEY_NAME_N for each case | ||
- | The context is simply added after key name separated by an underscore. | + | Some examples would be: |
- | Plurals are written like in gettext way. For a language with 2 plural forms, you keep KEY_NAME for singular and KEY_NAME_PLURAL for plural. For a language with 3 or more plural forms, it will be KEY_NAME_0, KEY_NAME_1, ..., KEY_NAME_N for each cases | + | * <wrap hi>cbtranslation::get('friend','Users',array('language'=>'en_us'))</wrap> which will search in english |
+ | * <wrap hi>cbtranslation::get('friend','Users',array('language'=>'es_es'))</wrap> which will search in spanish | ||
+ | * <wrap hi>cbtranslation::get('friend','Users',array('language'=>'en_us','count'=>2))</wrap> which will search in english for the plural form of the label: 'friend_PLURAL' | ||
+ | * <wrap hi>cbtranslation::get('friend','Users',array('language'=>'en_us','count'=>1))</wrap> which will search in english for the singular form of the label: 'friend' | ||
+ | * <wrap hi>cbtranslation::get('friend','Users',array('language'=>'en_us','count'=>2, 'context'=>'female'))</wrap> which will search in english for the plural form of the label with 'female' suffix: 'friend_female_PLURAL' | ||
- | Mix of both is on the form KEY_NAME_CONTEXT_PLURAL for example. | + | Finally, you can add more parameters to support sprintf formatting like this: <wrap hi>cbtranslation::get('friendcountry','Users',array('language'=>'en_us','context'=>'female','count'=>2),2,'England')</wrap> |
+ | |||
+ | You can [[https://github.com/tsolucio/coreBOSTests/blob/master/modules/cbtranslation/cbtranslationTest.php|find a set of examples in our unit test for this module]]. | ||
===Examples=== | ===Examples=== | ||
- | Let's say that we have these values (totally useless in real life) : | + | Let's say that we have these values |
- | in language/en_us.lang.php | ||
<code> | <code> | ||
- | $app_strings = array( | ||
'LBL_USER' => 'User', | 'LBL_USER' => 'User', | ||
'LBL_USER_PLURAL' => 'Users', | 'LBL_USER_PLURAL' => 'Users', | ||
- | 'LBL_USER_MALE' => 'Mister User', | + | 'LBL_USER_MALE' => 'Male User', |
- | 'LBL_USER_FEMALE' => 'Miss User', | + | 'LBL_USER_FEMALE' => 'Female User', |
+ | 'LBL_USER_FEMALE_PLURAL' => 'Many female users', | ||
'LBL_CONNECTED_USERS' => '%d user is connected', | 'LBL_CONNECTED_USERS' => '%d user is connected', | ||
'LBL_CONNECTED_USERS_PLURAL' => '%d users are connected', | 'LBL_CONNECTED_USERS_PLURAL' => '%d users are connected', | ||
- | ); | ||
- | </code> | ||
- | <code> | ||
- | $mod_strings = array( | ||
- | 'LBL_USER_MALE_PLURAL' => 'Many main males users', | ||
- | 'LBL_USER_FEMALE_PLURAL' => 'Many main female users', | ||
- | ); | ||
</code> | </code> | ||
- | Calling <wrap hi>__('LBL_USER')</wrap> will return 'LBL_USER' because no key is defined in vtiger.php | + | Calling <wrap hi>cbtranslation::get('LBL_USER', $MODULE)</wrap> will return 'User' |
- | Calling <wrap hi>__m('LBL_USER', $MODULE)</wrap> in a users Module layout will return 'User' | + | Calling <wrap hi>cbtranslation::get('LBL_USER', $MODULE, array('count'=>$CONNECTED_USERS_COUNT))</wrap> will return 'Users' if $CONNECTED_USERS_COUNT > 1 and 'User' if $CONNECTED_USERS_COUNT = 1 |
- | Calling <wrap hi>__mn('LBL_USER', $MODULE, $CONNECTED_USERS_COUNT)</wrap> in a users module layout will return for instance '10 users are connected' | + | Calling <wrap hi>cbtranslation::get('LBL_CONNECTED_USERS', $MODULE, array('count'=>$CONNECTED_USERS_COUNT),$CONNECTED_USERS_COUNT)</wrap> will return for instance '10 users are connected' |
- | Calling <wrap hi>__mxn('LBL_USER', $MODULE, 'FEMALE', $CONNECTED_USERS_COUNT)</wrap> in a users module layout will return 'Miss User' if $CONNECTED_USERS_COUNT = 1 and 'Many main female users' if $CONNECTED_USERS_COUNT > 1 (fallback to main translation file) | + | Calling <wrap hi>cbtranslation::get('LBL_USER', $MODULE, array('context'=>'FEMALE','count'=>$CONNECTED_USERS_COUNT))</wrap> will return 'Female User' if $CONNECTED_USERS_COUNT = 1 and 'Many female users' if $CONNECTED_USERS_COUNT > 1 |
+ | ===== cbtranslation webservice===== | ||
+ | There is currently no webservice interface to this module's translation services. We could enhance the webservice getTranslatedString method, which, I think, would be the correct way to proceed. | ||
+ | In the mean time, a normal query should get you the translation you need: | ||
+ | <code SQL> | ||
+ | select i18n from cbtranslation where translation_key = 'friend' and locale='es_es' | ||
+ | select i18n,Products.productname from cbtranslation where Products.productname = 'Sexy Leggings'; | ||
+ | </code> | ||
=====References===== | =====References===== | ||
+ | |||
+ | This enhancement to coreBOS is based on the [[http://code.vtiger.com/vtiger/vtigercrm/merge_requests/238|work of @bertrand.wattel]]. **Thank you very much!!** I'm sure vtiger will pay just as much attention to your effort as I did LOL | ||
*http://code.vtiger.com/vtiger/vtigercrm/merge_requests/238 | *http://code.vtiger.com/vtiger/vtigercrm/merge_requests/238 |