View Issue Details

IDProjectCategoryView StatusLast Update
0026631LazarusLCLpublic2015-01-05 17:58
ReporterDenis KozlovAssigned ToMaxim Ganetsky 
PrioritynormalSeverityminorReproducibilityN/A
Status resolvedResolutionfixed 
Product Version1.2.4Product BuildLazarus 1.2.4 r45510 FPC 2.6.4 
Target VersionFixed in Version1.4 
Summary0026631: On demand localization instead of forced at init section in DefaultTranslator
DescriptionDefaultTranslator 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.
TagsDefaultTranslator, i18n, Language, SetDefaultLang
Fixed in Revision47310
LazTarget-
Widgetset
Attached Files

Relationships

related to 0026688 resolvedMaxim Ganetsky DefaultTranslator patch 

Activities

Denis Kozlov

2014-08-25 16:15

reporter   ~0076711

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);".

Juha Manninen

2014-08-25 19:18

developer   ~0076712

> 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.

Maxim Ganetsky

2014-08-25 22:42

developer   ~0076714

Last edited: 2014-08-25 22:42

View 2 revisions

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.

Denis Kozlov

2014-08-27 00:35

reporter   ~0076728

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.

wp

2014-08-29 18:20

developer   ~0076781

I agree with dezlov

Bart Broersma

2014-08-29 19:11

developer   ~0076783

Control the behaviour via compiler directive?

Denis Kozlov

2014-09-09 23:34

reporter   ~0077016

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.

Maxim Ganetsky

2014-09-26 01:17

developer   ~0077674

Last edited: 2014-09-26 01:17

View 2 revisions

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.

Denis Kozlov

2014-10-27 11:20

reporter  

ExampleLanguageSwitchingCarryOver.zip (130,077 bytes)

Denis Kozlov

2014-10-27 11:30

reporter   ~0078642

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

Steps:
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.

Maxim Ganetsky

2015-01-05 17:58

developer   ~0080137

Factored out LCLTranslator unit from DefaultTranslator. The latter still behaves as before.

Please test and close if OK.

Issue History

Date Modified Username Field Change
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