Lazarus localization / multiple projects - lazarus

I've got some Delphi experience and I'm trying to build a project with Lazarus, which is completely new for me.
I think, I've read all information available about Lazarus,Translating/Internationalization/Localization, but I was unable to find what I really want.
I've been working in a project with 3 or 4 EXEcutables, that share between them, the same database the same Interface (form inheritance), common utils, settings, and common and related strings.
I don't want to have 3 or 4 .po files with different names (one for each EXE) , with the same common strings shared between them.
Is there a solution for that?
probably force ONE "gobal.po" for all Apps? how?
do I have to create my own system to localize \ centralize all strings in ONE file?
any suggestions?
thanks for any help.
regards,

Use a shared language unit into which you put all the strings of all projects. Create a package into which you add this shared strings unit. Turn i18n on for this package. Compile the package and you'll get the shared po file in the languages folder.
For every project needing the resource strings, you must add this package as a requirement - the easiest way to do this is in the package editor and to select "Use" / "Add to project".
Don't turn on i18n for the projects because this would add the project po files to the languages folder.
In order to use translated strings in each project, add the unit "Translations" to uses and call
TranslateUnitResourceStrings(
StringsUnit,
Format('languages\%s.%s.po', [StringsUnit, ALang])
);
Here StringsUnit is the name of the shared unit with all the collected resource strings. ALang is the language symbol to be used, e.g. 'de' for German, 'fr' for French etc.
And now the hard part... Since i18n is off, the strings assigned to captions of components are not automatically put into the po file. So, you leave the component captions alone, create a resource string for each one (in the 'stringsunit', of course), and then, at runtime, assign the captions to the resourcestring. Maybe something like this:
procedure TForm1.FormCreate(Sender: TObject);
begin
SetCaptions;
end;
procedure TForm1.SetCaptions;
begin
Caption := RSTitleOfForm1; // resource string for form title
Label1.Caption := RSYDateLabel; // label caption showing "Date:"
// etc.
end;
If the user selects a new language, for example from a combobox with all the available translations, you must call TranslateUnitResourceStrings and then SetCaptions for each existing form (in case of dynamically created forms, SetCaptions will be called automatically since it is in the FormCreate event).

Related

Lazarus messagebox: how to localize buttons

I want to localize buttons of MesssageBox, MessageDlg, InputQuery, etc.
I see resourcestring exist for this in lclstrconsts: "OK"/"Cancel".... but I want to set button strings using asssignments.
How to do it?
I need it on Win32. I see that German/Rus OS shows En buttons.
That's how it is done for MessageDlg: http://delphi.xcjc.net/viewthread.php?tid=47562.
Variables with rs prefix should be defined.
Other components could be localized the same way.
There are several articles in the wiki about localization:
Translating/Internationalization/Localization
In short:
Set "Enable i18n" at the project options -> i18n, set PO Output Directory (locale for example)
Recompile project
Copy created yourproject.po file to yourproject.de.po, yourproject.it.po and so on for desired languages into the same directory.
Copy to locale directory of your project *.po files from lazarus/lcl/languages to translate LCL.
Add unit LCLTranslator to the uses clause of your main form.
Call SetDefaultLang('it'); somewhere to set desired translation (Italian in this example). Check is all Ok by inspecting GetDefaultLang function result.
Note that (3) is required.
You may find ready to use POs in other thirdparty libraries if any.

WinRT Localization - Multiple Translations per Language

I am building a Windows Store application in XAML/C# for a Windows 8.1 Professional environment.
My project has a requirement that I must support multiple languages in addition to multiple translations for any given language. For example, I may have a label that would be displayed in English or French, but in English it may need to display the word "Title" or the word "Heading" depending on the customer's preferences.
My issue is that I cannot figure out a way to package and switch between multiple resource dictionaries for the same language while still using the built-in localization functionality provided by XAML for WinRT (i.e. using the Uid property on my controls to bind them to a resource dictionary).
I've noticed two functions, ResourceManager.LoadPriFiles and ResourceManager.UnloadPriFiles, that I thought might allow me to swap out resource dictionaries at runtime, but I can't figure out how to get the PRI files to be package outside of the application's main resource map to allow the loading and unloading.
I've also considered creating a custom data binding or converter that I could use to bind the controls' text manually, but that would cost me the ability to see labels at design time in Blend as well as sacrificing the convenience of the built-in localization capabilities.
Another option was to compile a separate instance of the application for each of the custom translations the customer might require, but obviously that's not a very maintainable way of solving the issue...
Finally, I had considered repurposing something like the homeregion qualifier of the ResourceContext to solve the issue; however, that seems very limiting as there are already pre-established homeregions that I would have to choose from. Repurposing fields seems like a bad idea in general.
You can use several resources files and use the PrimaryLanguageOverride property to select a different language than the default one. This will allow you to change the current resources set without doing anything specific.
You can use a structure like this one for your resources:
Strings
+- en-US
+-Resources.resw
+- fr-FR
+-Resources.resw
+- fr-other
+-Resources.resw
Then in you code, you will just have to call any of the following lines :
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "fr-other";
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "en-US";
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "fr-FR";
You application will now use the "fr-other" language. You can use up to 8 characters in the second part of the language tag.

Can we use control the source formats/layout in DMExpress using environment variables?

I am using DMExpress tasks to do taransformations on my business data. These business data come in multiple format/layout. I need to be able to use single task for transformation on multiple source layouts. Any DMExpress experts here??
One way that I found out for doing transformation on multiple source layouts with the help of single task was by using the Dmexpress SDK to write the script for the task rather than building the tasks using the GUI task editor. SDK gives lot more flexibility compared to the GUI editor.
But if you are bound to GUI then there is a way around for this specific purpose. You should define a common name for the source layout. Only the source layout name is binded to the task but not the actual layout definition. So you can alter the layout definition while keeping the layout name constant to get a generic task.
FYI- DMExpress is now called DMX (Syncsort changed the name about a year ago).
Do you have multiple different record types within a single file or is each type of record in a separate file? Your question is not clear on this.
If they are in separate files, this is very easy, but you will need to create a separate DMX task for each file. In each of these tasks, define one of the files as the source and create a record layout that matches the format of that file.
If they are in the SAME file, it is only a little more difficult. You can split them into separate files by creating multiple targets and defining a named condition for each target using the SourceName() function (this function returns the name of the file that the current record came from). Then you can process them as separate files (see above). This works UNLESS you have a parent-child relationship going on between the different types of records in that single file. If that is the case, please post some sample data and I can advise on how to handle it.

Using string-type resource identifiers in Windows .rc files / dlls

We have a number of MFC extension dlls in our code base, many of which have embedded Windows resources defined in the projects .rc files (IDS_..., IDD_..., IDB_... etc). We use numerical identifiers to define our resources, taking special care that our resource ids don't clash across dlls, which requires some management to ensure our developers don't use the same numberings.
I've realised that string-type resource identifiers might be an easy way to go, meaning that we can define unique identifiers for each resource in each different dll.
My question is, are there any technical problems with doing this, for example:
Will the MFC dll / resource chain still function correctly?
Will the Visual Studio resource editor still work?
I haven't found anything in the MS Technical Notes to say this would be a problem - I'd just wondering if people have had experience with this.
Note however that IDs of strings in the string table (IDS_) MUST be numeric (16 bits IIRC). The difference between a string and another resource is due to strings not being individual resources. Actually, the string table consists in a set of resources, each containing up to 16 strings with consecutive IDs.
Same goes for Control IDs within dialogs. But you most likely know that.
In the resource editor, you can specify a string resource id in the property grid by simply putting quotes around the resource names.
Regarding dialogs and the resource editor: You'll have a minor problem: Whenever you create a class for the dialog, the generated code contains enum { IDD = resourceid }. Needless to say that it won't work for a string id. But you can easily get rid of this IDD enum and replace it by a string.

What are the best practices for building multi-lingual applications on win32?

I have to build a GUI application on Windows Mobile, and would like it to be able user to choose the language she wants, or application to choose the language automatically. I consider using multiple dlls containing just required resources.
1) What is the preferred (default?) way to get the application choose the proper resource language automatically, without user intervention? Any samples?
2) What are my options to allow user / application control what language should it display?
3) If possible, how do I create a dll that would contain multiple language resources and then dynamically choose the language?
For #1, you can use the GetSystemDefaultLangID function to get the language identifier for the machine.
For #2, you could list languages you support and when the user selects one, write the selection into a text file or registry (is there a registry on Windows Mobile?). On startup, use the function in #1 only if there is no selection in the file or registry.
For #3, the way we do it is to have one resource DLL per language, each of which contains the same resource IDs. Once you figure out the language, load the DLL for that language and the rest just works.
Re 1: The previous GetSystemDefuaultLangID suggestion is a good one.
Re 2: You can ask as a first step in your installation. Or you can package different installers for each language.
Re 3:
In theory the DLL method mentioned above sounds great, however in practice it didn't work very well at all for me personally.
A better method is to surround all of the strings in your program with either: Localize or NoLocalize.
MessageBox(Localize("Hello"), Localize("Title"), MB_OK);
RegOpenKey(NoLocalize("\\SOFTWARE\\RegKey"), ...);
Localize is just a function that converts your english text to a the selected language. NoLocalize does nothing.
You want to surround your strings with these values though because you can build a couple of useful scripts in your scripting language of choice.
1) A script that searches for all the Localize(" prefixes and outputs a .ini file with english=otherlangauge name value pairs. If the output .ini file already contains a mapping you don't add it again. You never re-create the ini file completely, your script just adds the missing ones each time you run your script.
2) A script that searches all the strings and makes sure they are surrounded by either Localize(" or NoLocalize(". If not it tells you which strings you still need to localize.
The reason #2 is important is because you need to make sure all of your strings are actually consciously marked as needing localization or not. Otherwise it is absolutely impossible to make sure you have proper localization.
The reason for #1 instead of loading from a DLL is because it takes no work to maintain this solution and you can add new strings that need to be translated on the fly.
You ship the ini files that are output with your program. You also give these ini files to your translators so they can convert the english=otherlanguage pairs. When they send it back to you, you simply replace your checked in .ini file with the one given by your translator. Running your script as mentioned in #1 will re-add any missing translations if any were done while the translator was translating.

Resources