View Issue Details
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0026631||Lazarus||LCL||public||2014-08-25 15:40||2015-01-05 17:58|
|Reporter||Denis Kozlov||Assigned To||Maxim Ganetsky|
|Product Version||1.2.4||Product Build||Lazarus 1.2.4 r45510 FPC 2.6.4|
|Target Version||Fixed in Version||1.4|
|Summary||0026631: On demand localization instead of forced at init section in DefaultTranslator|
|Description||DefaultTranslator unit is great for enabling localization in projects. It has however a major drawback. It calls SetDefaultLang('') at initialization section, which means that any application that imports this unit get the benefit of localization but without much control over the selected language.|
Please remove SetDefaultLang('') from initialization section, so that the application can control which language to load or whether to load it at all. Please keep reading for a more detailed explanation and a non-breaking implementation.
SetDefaultLang('') picks up the language from system locale, LANG environment variable and --lang command line option. These are great, but again provide no control for the application over which language is loaded. The reason why it is called from initialization section is to make sure that no forms have been created, at a cost of losing control.
Automatically detecting the desired language does not always produce desired results for the end user. Many users have systems with different locales to what their proffered UI language is, while others prefer to use English UI language despite the locale setting, etc.
Calling SetDefaultLang multiple times is not a good option. Apart from obvious overhead, if the second call uses a language file with partial translations then non-translated visual components will still contain a language loaded during automatic translation at the initialization stage, instead of the original text.
Applications normally give users an option to select their preferred language, so it should be able to load a user selected language at start-up. Alternatively, if user has not chosen any language yet - then load an automatically detected one.
There is a way to implement this without breaking compatibility for applications which rely on SetDefaultLang being called at initialization stage.
1) Remove SetDefaultLang('') from initialization section in DefaultTranslator.pas.
2) Rename DefaultTranslator.pas to DefaultTranslatorBase.pas (or similar).
3) Create an empty DefaultTranslator.pas unit which simply imports DefaultTranslatorBase.pas and calls SetDefaultLang('') at initialization stage.
This gives the best of both, by keeping original operation of DefaultTranslator and allowing applications to control the loaded language by importing DefaultTranslatorBase instead of DefaultTranslator.
But if backwards compatibility is not important in this case - then simply remove SetDefaultLang('') from initialization section.
|Tags||DefaultTranslator, i18n, Language, SetDefaultLang|
|Fixed in Revision||47310|
I forgot to mention:
Once "SetDefaultLang('');" is removed from initialization section, then "LRSTranslator.Free;" in finalization section should be replaced by "if Assigned(LRSTranslator) then FreeAndNil(LRSTranslator);".
> if Assigned(LRSTranslator) then FreeAndNil(LRSTranslator);
No, such code is never needed. Free can be called on a Nil reference. See TObject.Free for details.
DefaultTranslator is meant to be simple translation unit that works out of the box (by just including it in uses clause).
If you need something more complicated, you should use "translations" unit.
Maxim, but this minor change only adds flexibility without changing the way it currently works.
It will remain a simple translation unit that works out of the box, by just including it in uses clause.
Please, split it into DefaultTranslator and DefaultTranslatorBase as described above.
People like me won't have to always copy a 1 line modified version of DefaultTranslator to every project, and re-do it with every update.
||I agree with dezlov|
||Control the behaviour via compiler directive?|
||Compiler directive could help, but is more of a band-aid rather than a solution. Splitting into 2 separate units is the best approach I think.|
Can you provide test project which demonstrates this:
> if the second call uses a language file with partial translations then non-translated visual components will still contain a language loaded during automatic translation at the initialization stage, instead of the original text.
ExampleLanguageSwitchingCarryOver.zip (130,077 bytes)
Example project attached.
It contains 3 PO files:
* project1.po - generated by Lazarus
* project1.a.po - language A with both labels translated
* project1.b.po - language B with only one label translated
1) Click on "Lang A" button to load PO file with both labels translated.
2) Click on "Lang B" button to load PO file with only one label translated.
3) The second label will contain translation from "Lang A", while it should revert back to orignal text when PO file doesn't contain translated text. So we get a mix of languages from different PO files.
Factored out LCLTranslator unit from DefaultTranslator. The latter still behaves as before.
Please test and close if OK.
|2014-08-25 15:40||Denis Kozlov||New Issue|
|2014-08-25 15:43||Denis Kozlov||Tag Attached: DefaultTranslator|
|2014-08-25 15:43||Denis Kozlov||Tag Attached: i18n|
|2014-08-25 15:43||Denis Kozlov||Tag Attached: Language|
|2014-08-25 15:43||Denis Kozlov||Tag Attached: SetDefaultLang|
|2014-08-25 16:15||Denis Kozlov||Note Added: 0076711|
|2014-08-25 19:18||Juha Manninen||Note Added: 0076712|
|2014-08-25 22:42||Maxim Ganetsky||LazTarget||=> -|
|2014-08-25 22:42||Maxim Ganetsky||Note Added: 0076714|
|2014-08-25 22:42||Maxim Ganetsky||Status||new => resolved|
|2014-08-25 22:42||Maxim Ganetsky||Resolution||open => no change required|
|2014-08-25 22:42||Maxim Ganetsky||Assigned To||=> Maxim Ganetsky|
|2014-08-25 22:42||Maxim Ganetsky||Note Edited: 0076714||View Revisions|
|2014-08-27 00:35||Denis Kozlov||Note Added: 0076728|
|2014-08-27 00:41||Denis Kozlov||Status||resolved => assigned|
|2014-08-27 00:41||Denis Kozlov||Resolution||no change required => reopened|
|2014-08-29 18:20||wp||Note Added: 0076781|
|2014-08-29 19:11||Bart Broersma||Note Added: 0076783|
|2014-09-09 11:55||Juha Manninen||Relationship added||related to 0026688|
|2014-09-09 23:34||Denis Kozlov||Note Added: 0077016|
|2014-09-26 01:17||Maxim Ganetsky||Note Added: 0077674|
|2014-09-26 01:17||Maxim Ganetsky||Status||assigned => feedback|
|2014-09-26 01:17||Maxim Ganetsky||Note Edited: 0077674||View Revisions|
|2014-10-27 11:20||Denis Kozlov||File Added: ExampleLanguageSwitchingCarryOver.zip|
|2014-10-27 11:30||Denis Kozlov||Note Added: 0078642|
|2014-10-27 11:30||Denis Kozlov||Status||feedback => assigned|
|2015-01-05 17:58||Maxim Ganetsky||Fixed in Revision||=> 47310|
|2015-01-05 17:58||Maxim Ganetsky||Note Added: 0080137|
|2015-01-05 17:58||Maxim Ganetsky||Status||assigned => resolved|
|2015-01-05 17:58||Maxim Ganetsky||Fixed in Version||=> 1.4|
|2015-01-05 17:58||Maxim Ganetsky||Resolution||reopened => fixed|