Internationalisierung und Lokalisierung einer Kotlin / Native-Anwendung

Good ん に ち は oder guten Tag auf Japanisch.





Unabhängig davon, wie beliebt die englische Sprache ist, fühlen sich Benutzer in ihrer Muttersprachenumgebung immer noch wohler und vertrauter.





Im Folgenden wird daher Schritt für Schritt erläutert, wie eine Konsolenanwendung für Linux unter Kotlin / Native an russische und englische Ländereinstellungen angepasst wird.





Der gute alte GNU gettext wird uns dabei helfen .





Infolgedessen werden wir sicherstellen, dass dies überhaupt nicht beängstigend ist.





Lassen Sie uns gleichzeitig die Integration in C-Bibliotheken betrachten, die die Funktionen von Kotlin / Native erheblich erweitert.





Was wir schreiben: ein Übersetzer von Kardinalzahlen ins Japanische.





Was vom Leser erwartet wird: Kenntnisse der Programmiersprachen Kotlin, C, eine grundlegende Vertrautheit mit dem Linux-Betriebssystem (insbesondere Bash).





Was Sie dabei benötigen: jede Linux-Distribution, jede Version von IntelliJ IDEA, gettext-devel installiert oder ähnliches.





Motivation

Warum eigentlich Kotlin / Native und was hat Japanisch damit zu tun?

Seit etwa einem halben Jahr lerne ich langsam und traurig Japanisch aus dem Lehrbuch „Minna no Nihongo“: teils für die Übersetzung der Texte, teils nur aus Interesse an Kultur.





Später entschied ich mich, von der Systementwicklung zur Anwendungsentwicklung, vom Desktop zur mobilen Plattform, von C ++ / Qt / STL zu Kotlin / JVM / Android SDK zu wechseln.





, . , , NIH- - , ?





Qt/QML/C++: - .





Qt Open Source, - .





Kotlin Kotlin/Native.





, - .





Kotlin/Native

Kotlin " " () Java, JVM.





JetBrains, Kotlin, .





, (Kotlin/JS) "" (Kotlin/Native).





Kotlin/Native 2017 , .





Kotlin LLVM, JVM .





, .





:





  • (Apache-2.0 license)





  • LLVM , iOS













  • "" Kotlin





  • interop C





  • : low-level , POSIX





:





  • JVM, (: Native )





  • GUI, C interop (GTK, libui)





  • Android Studio,









Kotlin/Native , Github.





(i18n): , .





(l18n): , .





: "" , , , . .





GNU gettext

, .





GNU Translation Project.





:













  • runtime









GNU gettext

Kotlin/JVM Android Android SDK, , JVM.  





Kotlin/Native .





Qt , Qt, C++ .





GNU gettext:





  • ( )





  • (Win/Mac/Linux, Android/iOS )

















: Linux, .





: stdin, .





, .





Github IntelliJ IDEA.





: ~18 Ryzen 3900X + 32GB DDR4-3600 + NVM-E SSD. .





, .





:





$ file build/bin/native/debugExecutable/JapaneseNumeralTranslator.kexe
build/bin/native/debugExecutable/JapaneseNumeralTranslator.kexe: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.16, BuildID[xxHash]=a0971dbf76e9db60, with debug_info, not stripped

$ ldd build/bin/native/debugExecutable/JapaneseNumeralTranslator.kexe
	linux-vdso.so.1 (0x00007fff890d7000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f348e47a000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f348e334000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f348e312000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f348e2f7000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f348e12c000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f348e4a0000)
	libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f348e112000)
	libutil.so.1 => /lib64/libutil.so.1 (0x00007f348e10b000)
	libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f348e0d1000)
	librt.so.1 => /lib64/librt.so.1 (0x00007f348e0c6000)

$ file build/bin/native/releaseExecutable/JapaneseNumeralTranslator.kexe 
build/bin/native/releaseExecutable/JapaneseNumeralTranslator.kexe: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.16, BuildID[xxHash]=c76aff5e0db3fdae, not stripped

$ ldd build/bin/native/releaseExecutable/JapaneseNumeralTranslator.kexe 
	linux-vdso.so.1 (0x00007ffff69c2000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f41ad9dd000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f41ad897000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f41ad875000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f41ad85a000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f41ad68f000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f41ada03000)
	libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f41ad675000)
	libutil.so.1 => /lib64/libutil.so.1 (0x00007f41ad66e000)
	libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f41ad634000)
	librt.so.1 => /lib64/librt.so.1 (0x00007f41ad629000)

$ ls -lh build/bin/native/debugExecutable/JapaneseNumeralTranslator.kexe
-rwxr-xr-x. 1 eraxillan eraxillan 1.8M Mar  7 13:24 build/bin/native/debugExecutable/JapaneseNumeralTranslator.kexe

$ ls -lh build/bin/native/releaseExecutable/JapaneseNumeralTranslator.kexe 
-rwxr-xr-x. 1 eraxillan eraxillan 529K Mar  7 13:24 build/bin/native/releaseExecutable/JapaneseNumeralTranslator.kexe

      
      



, - .





, Community Edition.





, file .  





, IDE, .





, .





printf-driven , Android AOSP.





"" gettext().





, tr(), .





import kotlinx.cinterop.*
import platform.linux.*
import platform.posix.*

fun tr(key: String): String = gettext(key)?.toKString() ?: ""
      
      



POSIX-, Locale.kt.





: , .





, locale -a.





Bash- gettext:





  • create_localization.sh





  • update_localization.sh





, .





pot- (""), .





# Extract all tr() wrapped strings to po/jnt.pot file
xgettext --keyword=tr --language=java \
    --add-comments --sort-output \
    --copyright-holder='Alexander Kamyshnikov <axill777@gmail.com>' \
    --package-name='Japanese numeral translator' \
    --package-version='1.0' \
    --msgid-bugs-address='axill777@gmail.com' \
    -o po/jnt.pot --files-from=KT_FILES
      
      



po- ( ):





# Generate locale sources
# NOTE: --no-translator option is a workaround to supress email input request
msginit --no-translator --input=po/jnt.pot --locale=en_US.UTF-8 --output po/en_US/jnt.po
msginit --no-translator --input=po/jnt.pot --locale=ru_RU.UTF-8 --output po/ru_RU/jnt.po
      
      



mo- ( ):





# Generate locale binary files
msgfmt --output-file=po/en_US/jnt.mo po/en_US/jnt.po
msgfmt --output-file=po/ru_RU/jnt.mo po/ru_RU/jnt.po
      
      



, Kotlin/Native , "" mo- .





.





, Gradle, .





mo- , gettext .





RPM/DEB-, mo- /usr/share/locale



.





, , .





Während der Entwicklung müssen Sie nur regelmäßig update_localization.sh aufrufen , neue Zeilen übersetzen und dieses Skript erneut aufrufen, um Mo-Dateien zu generieren.





Thanks り が と う ご ざ い ま す oder danke für Ihre Aufmerksamkeit!





Quellen von

Definitionen aus der Django-Dokumentation 





Warum Internationalisierung und Lokalisierung wichtig sind





Kotlin Native: Beobachten Sie Ihre Dateien





DxGetText - GNU Gettext für Delphi und C ++ Builder





PS : Ich plane, Kotlin / Native im Rahmen plattformübergreifender Bibliotheken weiter zu verwenden. Bei Interesse kann ich die Demo ändern, z. B. auf Windows portieren.








All Articles