Hi
Deploying an application for the international market mostly requires some kind of localization (https://en.wikipedia.org/wiki/Multilingual_User_Interface).
In recent years, several online services have started offering online translations into a large number of languages, more than what is normally supported by a regular application.
In this sense, it would be nice to use these services on-site to translate the text resources into the target language chosen by the user and store them locally, avoiding further use of the translator.
From what I've seen, using such services can be done using a relatively simple HTTP API set and a user account. This last point requires registration and payment.
I was wondering how Google's Chrome does this since it doesn't require a login? Does anyone have an idea how it works? Any link or working example? :tongue:
Biterider
I've played with the idea, see attached multilingual editor, but with a slightly different approach:
- all GUI strings are handled in an Excel spreadsheet (attached)
- that implies getting translations for each column manually from Google or DeepL (https://www.deepl.com/translator)
- a copy gets saved in Utf8 format as GuiData.tab
- the tab file gets embedded as a resource
- the editor picks the language "on the fly" from that resource
You can test it using the Language menu entry.
Your version would go online to request the desired language for each GUI string, is that correct?
Hi
Quote from: jj2007 on November 13, 2022, 08:52:30 PM
Your version would go online to request the desired language for each GUI string, is that correct?
Yes, but only if the provided localization is not available. If you cannot go online, a default language, in most cases English, will be selected and must always be present.
Biterider
Hi
I found something on GitHub easygoogletranslate (https://github.com/ahmeterenodaci/easygoogletranslate)
The author claims that he uses an "unofficial Google Translate API".
I extracted the relevant request from the Python code
https://translate.google.com/m?tl=sv&sl=en&q=Open%20File (https://translate.google.com/m?tl=sv&sl=en&q=Open%20File) which, for example, translates "Open File" from English to Swedish
Available languages are listed here https://cloud.google.com/translate/docs/languages (https://cloud.google.com/translate/docs/languages)
Biterider
Try this link (https://www.deepl.com/translator#en/fr/%26File%0A%26New%0A%26Open%0A%26Save%0A%26Save%20as%E2%80%A6%0A%0AE%26xit%0A) for a change. It works in a browser, but not as a direct download request, unfortunately. They have an API, though, but it requires authentication, i.e. your user would have to register. That is one reason why I would prefer the Excel spreadsheet approach mentioned above: a few kBytes more embedded in the executable, but no hassle with registration etc
Hi
After all, it wasn't that difficult :cool:
Here is the unpolished code:
TranslateText proc uses xbx xdi, pDstLang:PSTRING, pSrcLang:PSTRING, pSrcText:PSTRING
local hInternet:HINTERNET, hConnect:HINTERNET, hRequest:HINTERNET
local dBytesRead:DWORD, pStartChar:POINTER, pTranslation:PSTRINGW
local pBuffer:POINTER, wDstBuffer[128]:CHRW, bURI[128]:CHRA
RCV_BUFFER_SIZE equ 4*PAGESIZE ;Reserve 4 pages, should be enough
mov pTranslation, NULL
invoke InternetOpen, $OfsCStr("Chrome/5.0"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0
.if xax != 0
mov hInternet, xax
invoke InternetConnect, hInternet, $OfsCStr("translate.google.com"), INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, NULL
.if xax != 0
mov hConnect, xax
lea xdi, bURI
WriteF xdi, "/m?hl=en&tl=¦ST&sl=¦ST&q=¦ST", pDstLang, pSrcLang, pSrcText
invoke HttpOpenRequest, hConnect, $OfsCStr("GET"), addr bURI, NULL, NULL, NULL, INTERNET_FLAG_RELOAD or INTERNET_FLAG_EXISTING_CONNECT or INTERNET_FLAG_SECURE, NULL
.if xax != 0
mov hRequest, xax
invoke HttpSendRequest, hRequest, NULL, 0, NULL, 0
invoke VirtualAlloc, NULL, RCV_BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE
.if xax != NULL
mov pBuffer, xax
mov xdi, xax
mov ebx, RCV_BUFFER_SIZE - 1
.repeat
invoke InternetReadFile, hRequest, xdi, ebx, addr dBytesRead
mov ecx, dBytesRead
.break .if eax == 0 || ecx == 0
add xdi, xcx
sub ebx, ecx
.until FALSE
mov CHRA ptr [xdi], 0
.if eax != 0
invoke StrPosA, pBuffer, $OfsCStrA(3Ch, 'div class="result-container"', 3Eh)
.if xax != NULL
add xax, 30
mov pStartChar, xax
invoke StrPos, xax, $OfsCStr(3Ch)
mov CHRA ptr [xax], 0
invoke UTF8ToWide, addr wDstBuffer, pStartChar, sizeof wDstBuffer
invoke StrNewW, addr wDstBuffer
mov pTranslation, xax
.endif
.endif
invoke VirtualFree, pBuffer, RCV_BUFFER_SIZE, MEM_RELEASE
.endif
invoke InternetCloseHandle, hRequest
.endif
invoke InternetCloseHandle, hConnect
.endif
invoke InternetCloseHandle, hInternet
.endif
mov xax, pTranslation
ret
TranslateText endp
For example, to translate "Open File" into Spanish, the code should look like this
invoke TranslateText, $OfsCStr("es"), $OfsCStr("en"), $OfsCStr("Open File")
.if xax != NULL
DbgStrW xax
invoke StrDispose, xax
.else
DbgWarning "No translation"
.endif
In this case the output is "Abrir documento"
Biterider
Hi Biterider!
But correct translation is "Abrir archivo" :biggrin: :biggrin: :biggrin:
HSE
Hi HSE
In this regard, DeepL does a better job.
Biterider
Quote from: Biterider on November 15, 2022, 05:57:36 PM
In this regard, DeepL does a better job.
If I need a translation, I rarely use Google. DeepL does an incredible job (and I can judge it, I am 100% fluent in 4 languages). Even very difficult phrases get translated correctly, it's really flabbergasting what these guys (https://www.deepl.com/translator#en/es/Open%20File) have achieved.
Hi
Looking at how DeepL can be used, it seems very complicated to use the web browser approach. It is easier to register and use the free version. Unfortunately, you have to give them your credit card information to register. An absolute no-go for me. :sad:
Biterider
With the Excel approach, see reply #1, DeepL is very easy to use. I select the English column:
&File
&New
&Open
&Save
&Save as...
E&xit
&Language
english
español
portogues
italiano
deutsch
français
Then I copy the column, paste it in DeepL and choose e.g. Spanish. Result:
&Archivo
&Nuevo
&Abrir
&Ahorro
&Guardar como...
E&Sit
&Idioma
inglés
english
portogues
italiano
alemán
francés
Ready to be pasted in the Spanish column of the spreadsheet, including even the ampersands :thumbsup:
And no hassle with registration or missing online access etc for the user.
Hi JJ
There are many other ways to get multilingual support, including your spreadsheet approach, but that's not the goal here.
As explained in the very first post, the concept I am following is using an online service on the customer side, as it is practically impossible to provide all the languages offered by these services.
BTW, I don't think that's the intended translation "E&Sit". It seems that the & is handled in a special way... Google has a similar issue.
Biterider
Hi
Looking again at the DeepL translations into Spanish using JJ's example, I saw the translation of "&Save" as "&Ahorro", which is completely wrong in this context. This shows me that this translator is also struggling with some isolated words. Maybe they can do better if the AI has more context from a full sentence.
Biterider
What is a best word for context ?
option &Save
opción &Guardar
Hi TimoVJL
Exactly, that's what I mean. If you try to precede each item with the word "menu" then the result will be correct.
I guess it acts like a hint for the AI. I don't know if it works in all situations, but I will try it.
Biterider
Hi
I'm starting to get something to work with. Now I pass a hint to the translation procedure:
CStr SrcLang, "en"
CStr DstLang, "de"
.code
start proc ;Program entry point
SysInit ;Runtime initialization of OOP model
DbgClearAll
OCall $ObjTmpl(Application)::Application.Init ;Initialize application
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("File"), $OfsCStr("Menu")
DbgStrW xax
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("Open File"), $OfsCStr("Menu")
DbgStrW xax
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("Open"), $OfsCStr("Menu")
DbgStrW xax
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("Save"), $OfsCStr("Menu")
DbgStrW xax
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("Save as..."), $OfsCStr("Menu")
DbgStrW xax
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("Print"), $OfsCStr("Menu")
DbgStrW xax
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("Exit"), $OfsCStr("Menu")
DbgStrW xax
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("Language"), $OfsCStr("Menu")
DbgStrW xax
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("English"), NULL
DbgStrW xax
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("Spanish"), NULL
DbgStrW xax
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("Portuguese"), NULL
DbgStrW xax
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("Italian"), NULL
DbgStrW xax
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("German"), NULL
DbgStrW xax
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("French"), NULL
DbgStrW xax
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("OK"), $OfsCStr("Button")
DbgStrW xax
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("Cancel"), $OfsCStr("Button")
DbgStrW xax
invoke TranslateText, offset DstLang, offset SrcLang, $OfsCStr("Search"), $OfsCStr("Button")
DbgStrW xax
; OCall $ObjTmpl(Application)::Application.Run ;Execute application
OCall $ObjTmpl(Application)::Application.Done ;Finalize application
SysDone ;Runtime finalization of the OOP model
invoke ExitProcess, 0 ;Exit program returning 0 to the OS
start endp
All results seem to be correct, at least for the languages I know
German
xax -> Datei
xax -> Datei öffnen
xax -> Öffnen
xax -> Speichern
xax -> Speichern unter...
xax -> Drucken
xax -> Beenden
xax -> Sprache
xax -> Englisch
xax -> Spanisch
xax -> Portugiesisch
xax -> Italienisch
xax -> Deutsch
xax -> Französisch
xax -> OK
xax -> Abbrechen
xax -> Suchen
Spanish
xax -> Archivo
xax -> Abrir archivo
xax -> Abrir
xax -> Guardar
xax -> Guardar como...
xax -> Imprimir
xax -> Salir
xax -> Idioma
xax -> Inglés
xax -> Español
xax -> Portugués
xax -> Italiano
xax -> Alemán
xax -> Francés
xax -> Aceptar
xax -> Cancelar
xax -> Buscar
Italian
xax -> File
xax -> Apri file
xax -> Apri
xax -> Salva
xax -> Salva con nome...
xax -> Stampa
xax -> Esci
xax -> Lingua
xax -> Inglese
xax -> Spagnolo
xax -> Portoghese
xax -> Italiano
xax -> Tedesco
xax -> Francese
xax -> OK
xax -> Annulla
xax -> Cerca
I can not check the correctness in other languages.
Maybe I can write a test application where other languages like Russian or Chinese can be selected and other forum members could check the results.
These are the results for now:
Russian
xax -> Файл
xax -> Открыть файл
xax -> Открыть
xax -> Сохранить
xax -> Сохранить как...
xax -> Печать
xax -> Выход
xax -> Язык
xax -> Английский
xax -> Испанский
xax -> Португальский
xax -> итальянский
xax -> Немецкий
xax -> Французский
xax -> ОК
xax -> Отмена
xax -> Искать
Simplified Chinese
Work in progress... :-)
Biterider
Traditional Chinese
xax -> 文件
xax -> 打開文件
xax -> 打開
xax -> 保存
xax -> 另存為...
xax -> 打印
xax -> 退出
xax -> 語言
xax -> 英語
xax -> 西班牙語
xax -> 葡萄牙語
xax -> 意大利語
xax -> 德語
xax -> 法語
xax -> 確定
xax -> 取消
xax -> 搜索
Biterider
Simplified(cn) - Traditional(tw)
开 - 開
为 - 為
语 - 語
确 - 確
Thanks learn64bit
I mixed the chinese language definitions. I corrected the above post.
The result for simplified chinese is
xax -> 文件
xax -> 打开文件
xax -> 打开
xax -> 保存
xax -> 另存为...
xax -> 打印
xax -> 退出
xax -> 语言
xax -> 英语
xax -> 西班牙语
xax -> 葡萄牙语
xax -> 意大利语
xax -> 德语
xax -> 法语
xax -> 确定
xax -> 取消
xax -> 搜索
Hindi
xax -> फ़ाइल
xax -> फ़ाइल खोलें
xax -> खोलें
xax -> सहेजें
xax -> इस रूप में सहेजें ...
xax -> प्रिंट
xax -> बाहर निकलें
xax -> भाषा
xax -> अंग्रेज़ी
xax -> स्पैनिश
xax -> पुर्तगाली
xax -> इतालवी
xax -> जर्मन
xax -> फ्रेंच
xax -> ठीक है
xax -> रद्द करें
xax -> खोज
Japanese
xax -> ファイル
xax -> ファイルを開く
xax -> 開く
xax -> 保存
xax -> 名前を付けて保存...
xax -> 印刷
xax -> 終了
xax -> 言語
xax -> 英語
xax -> スペイン語
xax -> ポルトガル語
xax -> イタリアの
xax -> ドイツ人
xax -> フランス語
xax -> OK
xax -> キャンセル
xax -> 検索
Biterider
Hi all
I ask those members who are fluent in the languages of the above posts to check that the translations are correct.
It would help me a lot to verify that the hints are working as intended.
Many thanks. :thumbsup:
Biterider
Hi
When translating a bunch of single words one after the other, the overall process is slow.
For this reason I am changing the strategy, collecting the words first and sending them all together in a single request. This means the response has to be parsed, but I think the speed gain is worth the effort.
Biterider
Hi
Bad news... :sad:
The free service seems to have some limitations: it can not process multiple lines at the same time.
It is designed to translate single sentences.
We have to live with it, which isn't a major problem for the current goal.
Biterider
Hi
As a proof of concept, I wrote a demo application that changes the main menu based on a user selection.
Alternatively, the machine locale could be used, but the demo was written to show their online translation capabilities.
Once a language has been selected via the "Languages" submenu (this submenu is intentionally excluded from the translation, preserving the native language names), a nice throbber will appear (only if the OS version is >= 8) while the translation is in action. :cool:
The final result is saved in a file, so that the next time the application is started, the last translation is immediately active.
For this demo I randomly selected only 10 languages from Google's list. It currently contains more than 90 languages.
Since the application resource section is filled with a large amount of throbber images, its size exceeds the upload limit of the forum. The application can be downloaded from GitHub using the following link https://github.com/ObjAsm/ObjAsm-C.1/raw/master/Projects/X/Multilingual%20GUI/ML_GUI.exe
The complete source code is also available on GitHub, but the original idea and code is posted above.
The code for single translations can be found in the attachment.
Biterider
Hi Biterider!
Quote from: Biterider on November 20, 2022, 09:13:32 PM
application resource section is filled with a large amount of throbber images
Nice, but to much. In Win7 (without throbber) translation is instantaneus. :thumbsup:
Quote from: Biterider on November 20, 2022, 09:13:32 PM
The complete source code is also available on GitHub
I cloned full repository in High Contrast machine.
Look fantastic. Still some dynamic layout metric is not perfect, because there are some superpositions (1 to 3 pixels, or so).
Object Explorer don't work. I was thinking I brokened that, but apparently wasn't me this time :biggrin:
HSE
No throbber on Win7-64, as expected, but the translation works fine, with a 3 second delay :thumbsup:
Hi
Thanks for testing :cool:
@HSE:
Knowing that a good friend uses HC, I invested some time to add some improvements :biggrin:
Can you send me a screenshot of the "dynamic layout" issue? It will help a lot to pinpoint the problem.
It may be that the ObjectExplorer is confused because I uploaded the file ObjAsm\code\OA_Info.stm which contains information about my own system. Try deleting the file and restarting the application.
I'll remove this file from GitHub too.
@JJ:
The few seconds delay is due to the running of the online service. It's not related to the application itself. I tried using a batch approach but it didn't work. Maybe sending multiple requests at once can solve the problem.
Since I haven't had any more time so far, I've installed the Throbber, which makes those few seconds go by much faster. :rolleyes:
Biterider
Quote from: Biterider on November 20, 2022, 09:13:32 PMAs a proof of concept, I wrote a demo application that changes the main menu based on a user selection.
Hi Biterider,
News from my own baby (http://masm32.com/board/index.php?topic=10401.msg116123#msg116123), with now about 700 translations :cool:
I have interest in foreign languages, so i downloaded language packs,for example japanese, would it be possible to get info from language pack instead?
Or some way to find windows data somewhere it keeps native meny texts?
.cpp for example in resource file dialogs for file, help,about box is kept there
So swedish version programs probably keep it there or indirect loads it from other files
@JJ
Fluent in x86,x64,German, Italian I guess :greenclp:
EnumUILanguagesA function (winnls.h) (https://learn.microsoft.com/fi-fi/windows/win32/api/winnls/nf-winnls-enumuilanguagesa?redirectedfrom=MSDN)
QuoteIn the registry is this
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\MUI\UILanguages\en-US]
"LCID"=dword:00000409
"Type"=dword:00000091
Some experiments:
https://forum.pellesc.de/index.php?topic=5324.msg20459#msg20459
void SetLang(HWND hwnd, LANGID lid)
{
typedef LANGID (WINAPI *fnSetThreadUILanguage) (LANGID wReserved);
HMENU hMenu;
if ((GetVersion() & 0x00FF) > 5) // Vista =>
{
fnSetThreadUILanguage fnPtr = (fnSetThreadUILanguage)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "SetThreadUILanguage");
if (fnPtr)
(*fnPtr) (lid);
} else
SetThreadLocale(MAKELCID(lid, SORT_DEFAULT));
hMenu = GetMenu(hwnd);
SetMenu(hwnd, NULL);
DestroyMenu(hMenu);
hMenu = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(2001));
SetMenu(hwnd, hMenu);
}
Is this, what you was after ?
Hi Biterider,
You might find these interesting:
https://translatepress.com/deepl-vs-google-translate-comparison/
QuoteWith both Google Translate and DeepL, you can translate up to 500,000 characters (not words) per month for free. This is 100% free forever. So as long as you stay under 500,000 characters per month, you could use either API for free.
https://blog.meinrad.cc/en/deepl-google-translate-not-all-machine-translation-engines-are-created-equal
QuoteThe real difference between these two engines is in the technology they use. Both use neural networks, but Google Translate (like most other machine translation engines) uses what are known as recurrent neural networks. By contrast, DeepL uses convolutional neural networks (CNNs), which produce better all-round results for longer, continuous sequences of words. Although CNNs aren't perfect, and so far haven't been used by other machine translation providers, they process texts better in parallel and produce better translations as a result.
Thanks JJ
Very interesting comparisons. From my experience, I agree with them. :thumbsup:
Biterider