As the globalization is deepening, the software is getting more and more like Dandelong, floating everywhere, rooted. This is to solve the display of different languages. We can certainly want a set, you can support different languages without modifying the code, do not maintain a lot of versions.
First, one problem to talk is to garbled, because Delphi Win32 to 11.x version still does not support Unicode, so the ANSI code is usually used, there are several cases show garbled:
Language text is different from the currently set language of the system; such as Simplified QQ in the traditional operating system (or the language of "non-Unicode program" in the regional setting of the Simplified Operating system) is garbled. Even if you change Font.Charset, some components will still appear garbled, such as STATUSBAR. Therefore, in the Vietnamese version of Windows display Vietnamese, WINDOWS in the Iranian version shows Iranian, don't display Iranian in Vietnamese version of Windows, showing Vietnamese in the Iranian version of Windows, so you can ensure that there is no garbled problem. It is not much better in general such misplaced usage.
The system does not have a language package you want to display;
If you want to ensure that you have completely unable code, you must consider using the Unicode code, using a set of support Unicode components, such as TNT, but it is more than the UI show, you can't use other components. For the words, first, first, see which places need to implement multilingual, and take a look at the advantages and disadvantages of various implementation methods. 1 , Such as the exception; 4, the above-described string inside the third party element package; there are many ways to implement multi-language, listing one or two: 1, Delphi comes with the resource generation tool this tool to put the task DFM file All strings and strings defined in the PAString are enumerated, and they can be compiled in different languages, and the text is selected first before compiling, each language is compiled into an EXE.
This tool is very inconvenient, not a complete solution, just like Borland's Midas Demo (TClientDataSet Connect to RemoteDataModule's TDataSetProvider through ProviderName, actually develop ERP system, who actually connects 100 TDataSetProvider to 100 TDataSet?) It is just a demonstration of a principle.
First of all, since DFM itself is also part of the resource file, it is "Update Resource Dlls ...", if you modify Button1 is Button2, if you forget, the runtime will report "Find the resource Button1 error "In the dictionary editing screen, the string is provided, and there is information such as Left / TOP; the dictionary cannot be reused, translated in a module, and then translate the same word again in the second module.
Second, each language is an Exe / BPL. If your system is Package cut, the BPL is also one of the languages, but also be careful not to combine the BPL combination of different languages. When you display Chinese, one shows German (There is a possibility that it may be garbled). Again, when the system is assembled as a BPL, if you do not provide a multi-language program, you need to modify the third party component, but we will not do this, because the third party is updated at any time, is it every time People update you will update people again.
Therefore, no one is provided with this scheme provided by Delphi itself (except Demo).
2, resource dll
Use a separate resourcedll to get a translated string with LoadRESSTRING, but you have to write this function to replace it, especially the strings on the form, 噢, will be exhausted. The dictionary can be reused. 3. Discussion on the online discussion This method is written to write a replacement engine, read the language string from the INI file at runtime to replace the display text of the screen element. This method is much larger than the first progress, no need to compile an exe for each language, just provide different INI files, if INI does not synchronize updates, no fatal mistakes, the most is a text has no conversion The engine also provides a string conversion function, so a message that can also be handled. This method has three different implementations in the file format: (1), [Number] = [String] Each string is numbered, 1, 2, 3, 4 ..., it is very troublesome. The code should be modified, of course, the language is not problematic when running. (2), [Component. Properties] = [String] This implementation corresponds to the component instance, and uses RTTI to determine attributes, replacing very accurate, or switching the language when running. Insufficient, slightly, the string of multiple components will be listed many times; there is no scalability, and the complex components such as TListView's columns are more effective. (3), [Old String] = [New Strings] Regardless of the component's instance, INI is a pure language comparison table, or call the dictionary, scalability, and running when switching the language may be in the engine. The deficiencies cannot handle the word polyfromance.
In general, this way has great progress, but in order to use Ini files, everyone will cost 64K limitations, more professional ways to use custom file formats. In terms of simplicity, this kind of custom conversion engine is undoubtedly, [old string] = [new string] file format is convenient, with a dictionary management tool, dictionary file can be reused, or you can provide professional translation company translation. Then the remaining problem is on the engine, how is it convenient, it is best not to write a line of code; how to scalability, support any third-party components; how to have flexible, the same screen has multiple languages, the same word can Convert to different meaning ... 4, inherit a subclass for each component class, convert the text in the Loaded method of the subclass. Since all the leave-level components (although TLABEL, TPANEL are coming from TCUSTOMCONTROL, but can only handle TCUSTOMCONTROL), the workload is relatively large; the old programs have no power to change the components. 5. Register a conversion function for each component class, the engine traverses the Container, finds the most recent conversion function of the blood source for each component, call this function to convert the text. This allows you to handle the leaf junction, just register the function on the appropriate component layer; you don't have to change the old program. When designing the Form, you only need to put a conversion element. This component starts scanning components on the Form after loading, from for i: = 0 to componentcount-1 or recursive from for i: = 0 to controlcount-1, find a component Go to find the nearest registration function of its blood, then call this function to replace its text. Because the registration function is additional plus, it will not be moved to the old code, which can be extended for any of the first components, and does not need to modify the code of the third party component of the people. I think the fifth method is very elegant, it looks more clean. Set with GOF design patterns, which belongs to Mediator Pattern. Many years ago, we used a component called TXPMenu to get the XP style interface. It also felt it very clean. When a component got everything, no TLabel changed to TFLATLABEL, TButton replaced with TFLATButton ... I remember "program There is also articles on the article specially praised this component. But that component does not use the intermediard mode, it is not well to extend support for the third party component. Finally, we think about it, if I am Borland, how to fully support multi-language in Delphi. Delphi provides a block-defined keyword "resourceString", in this block defined string constant, compile it to the resource area of the EXE file, run with loadStringa this Windows API to read, so some The external conversion tool can read these resource strings directly from the EXE file, write into the conversion string; the embedded conversion engine can also block this API function to convert the text. But if the string resources in the exe are not complete, it will be powerful. This is not completely just from Delphi's DFM file. Delphi puts the DFM file throughout the exe, and the strings on which they are can't decide. Don`t resource (many constant strings in Delphi source have this prompt).
If String, WideString, Ansistring, etc., Delphi adds a data type multistring, then modify the VCL component definition (Please Borland solved together with Unicode, "like TLabel.caption to MultiString, a multistring type, there is one Specialized treatment method, if resourcestring is handled with the LoadString API, convert it once each read, but it should be more than this content, such as the INSTANCE, then provide a global applicationMulti component, similar ApplicationEvent, let the outside Can capture. As for the dictionary, only external users can be provided (of course, one standard format can make Delphi people can share). This method looks viable, but there is also an efficiency problem to consider, (1) Each reading is transformed, low efficiency of frequent DRAW; How to use BeginUpdate / Endupdate, how the VCL informs the progeny to improve this efficiency. (Compensation: Efficiency does not seem to have a problem, change the multi-string change caused frequent DRAW, in fact, the component you have used BeginUpdate / endupdate, the externally will not involve)