Browse Source

Update GUI Translation demo for 4.0 (#930)

- Add PO support in addition to CSV.

Co-authored-by: SkyJJ <[email protected]>
Hugo Locurcio 1 year ago
parent
commit
5bda007763
59 changed files with 812 additions and 323 deletions
  1. 27 5
      gui/translation/README.md
  2. 0 0
      gui/translation/audio/hello_en.wav
  3. 24 0
      gui/translation/audio/hello_en.wav.import
  4. 0 0
      gui/translation/audio/hello_es.wav
  5. 24 0
      gui/translation/audio/hello_es.wav.import
  6. 0 0
      gui/translation/audio/hello_jp.wav
  7. 24 0
      gui/translation/audio/hello_jp.wav.import
  8. BIN
      gui/translation/audio/hello_ru.wav
  9. 24 0
      gui/translation/audio/hello_ru.wav.import
  10. BIN
      gui/translation/flag_japan.png
  11. BIN
      gui/translation/flag_spain.png
  12. BIN
      gui/translation/flag_uk.png
  13. 0 12
      gui/translation/font/droid_sans.tres
  14. 0 0
      gui/translation/fonts/DroidSans.ttf
  15. 5 4
      gui/translation/fonts/DroidSans.ttf.import
  16. 0 0
      gui/translation/fonts/DroidSansArabic.ttf
  17. 5 4
      gui/translation/fonts/DroidSansArabic.ttf.import
  18. 0 0
      gui/translation/fonts/DroidSansFallback.ttf
  19. 5 4
      gui/translation/fonts/DroidSansFallback.ttf.import
  20. 0 0
      gui/translation/fonts/DroidSansHebrew.ttf
  21. 5 4
      gui/translation/fonts/DroidSansHebrew.ttf.import
  22. 0 0
      gui/translation/fonts/DroidSansJapanese.ttf
  23. 5 4
      gui/translation/fonts/DroidSansJapanese.ttf.import
  24. 0 0
      gui/translation/fonts/DroidSansThai.ttf
  25. 5 4
      gui/translation/fonts/DroidSansThai.ttf.import
  26. 1 1
      gui/translation/fonts/LICENSE.DroidSans.txt
  27. 33 0
      gui/translation/fonts/droid_sans.tres
  28. 0 24
      gui/translation/hello_en.wav.import
  29. 0 24
      gui/translation/hello_es.wav.import
  30. 0 24
      gui/translation/hello_jp.wav.import
  31. BIN
      gui/translation/icon.webp
  32. 1 1
      gui/translation/icon.webp.import
  33. BIN
      gui/translation/images/flag_japan.webp
  34. 4 4
      gui/translation/images/flag_japan.webp.import
  35. BIN
      gui/translation/images/flag_russia.webp
  36. 34 0
      gui/translation/images/flag_russia.webp.import
  37. BIN
      gui/translation/images/flag_spain.webp
  38. 4 4
      gui/translation/images/flag_spain.webp.import
  39. BIN
      gui/translation/images/flag_uk.webp
  40. 4 4
      gui/translation/images/flag_uk.webp.import
  41. BIN
      gui/translation/images/speaker.webp
  42. 4 4
      gui/translation/images/speaker.webp.import
  43. 9 8
      gui/translation/project.godot
  44. BIN
      gui/translation/screenshots/translation.png
  45. BIN
      gui/translation/screenshots/translation.webp
  46. BIN
      gui/translation/speaker.png
  47. 0 4
      gui/translation/text.csv
  48. 0 17
      gui/translation/text.csv.import
  49. 47 0
      gui/translation/translation_csv.gd
  50. 0 32
      gui/translation/translation_demo.gd
  51. 0 131
      gui/translation/translation_demo.tscn
  52. 144 0
      gui/translation/translation_demo_csv.tscn
  53. 130 0
      gui/translation/translation_demo_po.tscn
  54. 44 0
      gui/translation/translation_po.gd
  55. 4 0
      gui/translation/translations/csv/text.csv
  56. 17 0
      gui/translation/translations/csv/text.csv.import
  57. 56 0
      gui/translation/translations/po/translation_demo.pot
  58. 62 0
      gui/translation/translations/po/translation_demo_es.po
  59. 61 0
      gui/translation/translations/po/translation_demo_ja.po

+ 27 - 5
gui/translation/README.md

@@ -1,14 +1,36 @@
 # GUI Translation Demo
 
-A demo showing how Godot seamlessly enables
-the use of localized resources and texts.
+This is a demo of how a project can be internationalized. Translations are
+created in a CSV file and then imported into Godot.
+
+For correct display, the font used must contain the glyphs required by the
+target language. See the `fonts` folder for some fonts that you can use in your
+project. Godot can load system fonts as a fallback, but this is not supported on
+all platforms and the different visual design of system fonts can create
+inconsistencies.
+
+Godot allows internationalized text to change automatically when the locale is
+modified. Resources can also be set to internationalized alternatives and replaced
+automatically on locale change. This process is known as *remapping*.
+
+Both CSV and gettext (PO/POT) approaches are showcased. Use the button in the
+bottom-right corner to switch between the two approaches.
+
+The resouce remapping process with PO is the same with CSV. The in-game text translation
+process is also the same – use keys to fetch the appropriate translation.
+
+The main difference between PO files and CSV files is the way both of them store
+the translated data in their files.  Have a look at the `translations/po`
+and `translations/csv` folders to see the files involved.
+
+See [Internationalizing games](https://docs.godotengine.org/en/latest/tutorials/i18n/internationalizing_games.html)
+and [Localization using gettext](https://docs.godotengine.org/en/latest/tutorials/i18n/localization_using_gettext.html)
+for more information.
 
 Language: GDScript
 
 Renderer: Compatibility
 
-Check out this demo on the asset library: https://godotengine.org/asset-library/asset/134
-
 ## Screenshots
 
-![Screenshot](screenshots/translation.png)
+![Screenshot](screenshots/translation.webp)

+ 0 - 0
gui/translation/hello_en.wav → gui/translation/audio/hello_en.wav


+ 24 - 0
gui/translation/audio/hello_en.wav.import

@@ -0,0 +1,24 @@
+[remap]
+
+importer="wav"
+type="AudioStreamWAV"
+uid="uid://ciept8j0x21to"
+path="res://.godot/imported/hello_en.wav-2eea592f221b07e3c37c5477c1da8173.sample"
+
+[deps]
+
+source_file="res://audio/hello_en.wav"
+dest_files=["res://.godot/imported/hello_en.wav-2eea592f221b07e3c37c5477c1da8173.sample"]
+
+[params]
+
+force/8_bit=false
+force/mono=false
+force/max_rate=false
+force/max_rate_hz=44100
+edit/trim=false
+edit/normalize=false
+edit/loop_mode=0
+edit/loop_begin=0
+edit/loop_end=-1
+compress/mode=0

+ 0 - 0
gui/translation/hello_es.wav → gui/translation/audio/hello_es.wav


+ 24 - 0
gui/translation/audio/hello_es.wav.import

@@ -0,0 +1,24 @@
+[remap]
+
+importer="wav"
+type="AudioStreamWAV"
+uid="uid://dd4xk00uh27hj"
+path="res://.godot/imported/hello_es.wav-0b3ee7fc19ef7ac4822f3f3dc177c570.sample"
+
+[deps]
+
+source_file="res://audio/hello_es.wav"
+dest_files=["res://.godot/imported/hello_es.wav-0b3ee7fc19ef7ac4822f3f3dc177c570.sample"]
+
+[params]
+
+force/8_bit=false
+force/mono=false
+force/max_rate=false
+force/max_rate_hz=44100
+edit/trim=false
+edit/normalize=false
+edit/loop_mode=0
+edit/loop_begin=0
+edit/loop_end=-1
+compress/mode=0

+ 0 - 0
gui/translation/hello_jp.wav → gui/translation/audio/hello_jp.wav


+ 24 - 0
gui/translation/audio/hello_jp.wav.import

@@ -0,0 +1,24 @@
+[remap]
+
+importer="wav"
+type="AudioStreamWAV"
+uid="uid://3tnymbrsqo0w"
+path="res://.godot/imported/hello_jp.wav-c7c916ef924fa85620d3858f227d094f.sample"
+
+[deps]
+
+source_file="res://audio/hello_jp.wav"
+dest_files=["res://.godot/imported/hello_jp.wav-c7c916ef924fa85620d3858f227d094f.sample"]
+
+[params]
+
+force/8_bit=false
+force/mono=false
+force/max_rate=false
+force/max_rate_hz=44100
+edit/trim=false
+edit/normalize=false
+edit/loop_mode=0
+edit/loop_begin=0
+edit/loop_end=-1
+compress/mode=0

BIN
gui/translation/audio/hello_ru.wav


+ 24 - 0
gui/translation/audio/hello_ru.wav.import

@@ -0,0 +1,24 @@
+[remap]
+
+importer="wav"
+type="AudioStreamWAV"
+uid="uid://dkuqg8u4fid5m"
+path="res://.godot/imported/hello_ru.wav-490e2b267af12af16807f2bf3de6d995.sample"
+
+[deps]
+
+source_file="res://audio/hello_ru.wav"
+dest_files=["res://.godot/imported/hello_ru.wav-490e2b267af12af16807f2bf3de6d995.sample"]
+
+[params]
+
+force/8_bit=false
+force/mono=false
+force/max_rate=false
+force/max_rate_hz=44100
+edit/trim=false
+edit/normalize=false
+edit/loop_mode=0
+edit/loop_begin=0
+edit/loop_end=-1
+compress/mode=0

BIN
gui/translation/flag_japan.png


BIN
gui/translation/flag_spain.png


BIN
gui/translation/flag_uk.png


+ 0 - 12
gui/translation/font/droid_sans.tres

@@ -1,12 +0,0 @@
-[gd_resource type="FontVariation" load_steps=7 format=3 uid="uid://duo4ycm3e6mrb"]
-
-[ext_resource type="FontFile" uid="uid://c7ujio1oqntre" path="res://font/DroidSansArabic.ttf" id="1"]
-[ext_resource type="FontFile" uid="uid://xesv5idkrqcd" path="res://font/DroidSansFallback.ttf" id="2"]
-[ext_resource type="FontFile" uid="uid://cft2167j0ba27" path="res://font/DroidSansHebrew.ttf" id="3"]
-[ext_resource type="FontFile" uid="uid://rdmplfeo1mfc" path="res://font/DroidSansJapanese.ttf" id="4"]
-[ext_resource type="FontFile" uid="uid://ctmwkt7kh6cst" path="res://font/DroidSansThai.ttf" id="5"]
-[ext_resource type="FontFile" uid="uid://33p1pmbcp0bh" path="res://font/DroidSans.ttf" id="6"]
-
-[resource]
-fallbacks = Array[Font]([ExtResource("4"), ExtResource("5"), ExtResource("3"), ExtResource("1"), ExtResource("2")])
-base_font = ExtResource("6")

+ 0 - 0
gui/translation/font/DroidSans.ttf → gui/translation/fonts/DroidSans.ttf


+ 5 - 4
gui/translation/font/DroidSans.ttf.import → gui/translation/fonts/DroidSans.ttf.import

@@ -2,19 +2,20 @@
 
 importer="font_data_dynamic"
 type="FontFile"
-uid="uid://33p1pmbcp0bh"
-path="res://.godot/imported/DroidSans.ttf-ba789e8a8b60473207799201d8a90bb4.fontdata"
+uid="uid://qaejxgrojp2d"
+path="res://.godot/imported/DroidSans.ttf-f4f3e617929333a8a3b131725141d728.fontdata"
 
 [deps]
 
-source_file="res://font/DroidSans.ttf"
-dest_files=["res://.godot/imported/DroidSans.ttf-ba789e8a8b60473207799201d8a90bb4.fontdata"]
+source_file="res://fonts/DroidSans.ttf"
+dest_files=["res://.godot/imported/DroidSans.ttf-f4f3e617929333a8a3b131725141d728.fontdata"]
 
 [params]
 
 Rendering=null
 antialiasing=1
 generate_mipmaps=false
+disable_embedded_bitmaps=true
 multichannel_signed_distance_field=false
 msdf_pixel_range=8
 msdf_size=48

+ 0 - 0
gui/translation/font/DroidSansArabic.ttf → gui/translation/fonts/DroidSansArabic.ttf


+ 5 - 4
gui/translation/font/DroidSansArabic.ttf.import → gui/translation/fonts/DroidSansArabic.ttf.import

@@ -2,19 +2,20 @@
 
 importer="font_data_dynamic"
 type="FontFile"
-uid="uid://c7ujio1oqntre"
-path="res://.godot/imported/DroidSansArabic.ttf-da8dabd885d494269ba77c8d78d8ed5b.fontdata"
+uid="uid://b6jt1itr5jreh"
+path="res://.godot/imported/DroidSansArabic.ttf-e3dcbe0c4bc0f3f609a01ac9b0b2d1d4.fontdata"
 
 [deps]
 
-source_file="res://font/DroidSansArabic.ttf"
-dest_files=["res://.godot/imported/DroidSansArabic.ttf-da8dabd885d494269ba77c8d78d8ed5b.fontdata"]
+source_file="res://fonts/DroidSansArabic.ttf"
+dest_files=["res://.godot/imported/DroidSansArabic.ttf-e3dcbe0c4bc0f3f609a01ac9b0b2d1d4.fontdata"]
 
 [params]
 
 Rendering=null
 antialiasing=1
 generate_mipmaps=false
+disable_embedded_bitmaps=true
 multichannel_signed_distance_field=false
 msdf_pixel_range=8
 msdf_size=48

+ 0 - 0
gui/translation/font/DroidSansFallback.ttf → gui/translation/fonts/DroidSansFallback.ttf


+ 5 - 4
gui/translation/font/DroidSansFallback.ttf.import → gui/translation/fonts/DroidSansFallback.ttf.import

@@ -2,19 +2,20 @@
 
 importer="font_data_dynamic"
 type="FontFile"
-uid="uid://xesv5idkrqcd"
-path="res://.godot/imported/DroidSansFallback.ttf-9bc560676e9de93a3474250e8f345fde.fontdata"
+uid="uid://cdrxhlo8nqckh"
+path="res://.godot/imported/DroidSansFallback.ttf-fefd6276707493f1293e2a65efe0de0d.fontdata"
 
 [deps]
 
-source_file="res://font/DroidSansFallback.ttf"
-dest_files=["res://.godot/imported/DroidSansFallback.ttf-9bc560676e9de93a3474250e8f345fde.fontdata"]
+source_file="res://fonts/DroidSansFallback.ttf"
+dest_files=["res://.godot/imported/DroidSansFallback.ttf-fefd6276707493f1293e2a65efe0de0d.fontdata"]
 
 [params]
 
 Rendering=null
 antialiasing=1
 generate_mipmaps=false
+disable_embedded_bitmaps=true
 multichannel_signed_distance_field=false
 msdf_pixel_range=8
 msdf_size=48

+ 0 - 0
gui/translation/font/DroidSansHebrew.ttf → gui/translation/fonts/DroidSansHebrew.ttf


+ 5 - 4
gui/translation/font/DroidSansHebrew.ttf.import → gui/translation/fonts/DroidSansHebrew.ttf.import

@@ -2,19 +2,20 @@
 
 importer="font_data_dynamic"
 type="FontFile"
-uid="uid://cft2167j0ba27"
-path="res://.godot/imported/DroidSansHebrew.ttf-2fc88dbe58ef638a09561323f2a293d1.fontdata"
+uid="uid://7bhkit5l8dka"
+path="res://.godot/imported/DroidSansHebrew.ttf-12677dba89ba8356d90dbb4569825058.fontdata"
 
 [deps]
 
-source_file="res://font/DroidSansHebrew.ttf"
-dest_files=["res://.godot/imported/DroidSansHebrew.ttf-2fc88dbe58ef638a09561323f2a293d1.fontdata"]
+source_file="res://fonts/DroidSansHebrew.ttf"
+dest_files=["res://.godot/imported/DroidSansHebrew.ttf-12677dba89ba8356d90dbb4569825058.fontdata"]
 
 [params]
 
 Rendering=null
 antialiasing=1
 generate_mipmaps=false
+disable_embedded_bitmaps=true
 multichannel_signed_distance_field=false
 msdf_pixel_range=8
 msdf_size=48

+ 0 - 0
gui/translation/font/DroidSansJapanese.ttf → gui/translation/fonts/DroidSansJapanese.ttf


+ 5 - 4
gui/translation/font/DroidSansJapanese.ttf.import → gui/translation/fonts/DroidSansJapanese.ttf.import

@@ -2,19 +2,20 @@
 
 importer="font_data_dynamic"
 type="FontFile"
-uid="uid://rdmplfeo1mfc"
-path="res://.godot/imported/DroidSansJapanese.ttf-de3fc871b57fb078f93cf2bf5d96545a.fontdata"
+uid="uid://b74c6j1be4nyv"
+path="res://.godot/imported/DroidSansJapanese.ttf-70e19a56601aacaaf5d6d308c2567f75.fontdata"
 
 [deps]
 
-source_file="res://font/DroidSansJapanese.ttf"
-dest_files=["res://.godot/imported/DroidSansJapanese.ttf-de3fc871b57fb078f93cf2bf5d96545a.fontdata"]
+source_file="res://fonts/DroidSansJapanese.ttf"
+dest_files=["res://.godot/imported/DroidSansJapanese.ttf-70e19a56601aacaaf5d6d308c2567f75.fontdata"]
 
 [params]
 
 Rendering=null
 antialiasing=1
 generate_mipmaps=false
+disable_embedded_bitmaps=true
 multichannel_signed_distance_field=false
 msdf_pixel_range=8
 msdf_size=48

+ 0 - 0
gui/translation/font/DroidSansThai.ttf → gui/translation/fonts/DroidSansThai.ttf


+ 5 - 4
gui/translation/font/DroidSansThai.ttf.import → gui/translation/fonts/DroidSansThai.ttf.import

@@ -2,19 +2,20 @@
 
 importer="font_data_dynamic"
 type="FontFile"
-uid="uid://ctmwkt7kh6cst"
-path="res://.godot/imported/DroidSansThai.ttf-91e10bcf58a298496a7fd92e1d4cd8c4.fontdata"
+uid="uid://t73gcvmo33on"
+path="res://.godot/imported/DroidSansThai.ttf-136cea21d69e1da7eb0a603f8d91fa3a.fontdata"
 
 [deps]
 
-source_file="res://font/DroidSansThai.ttf"
-dest_files=["res://.godot/imported/DroidSansThai.ttf-91e10bcf58a298496a7fd92e1d4cd8c4.fontdata"]
+source_file="res://fonts/DroidSansThai.ttf"
+dest_files=["res://.godot/imported/DroidSansThai.ttf-136cea21d69e1da7eb0a603f8d91fa3a.fontdata"]
 
 [params]
 
 Rendering=null
 antialiasing=1
 generate_mipmaps=false
+disable_embedded_bitmaps=true
 multichannel_signed_distance_field=false
 msdf_pixel_range=8
 msdf_size=48

+ 1 - 1
gui/translation/LICENSE.DroidSans.txt → gui/translation/fonts/LICENSE.DroidSans.txt

@@ -4,7 +4,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 
-     http://www.apache.org/licenses/LICENSE-2.0
+	 http://www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,

+ 33 - 0
gui/translation/fonts/droid_sans.tres

@@ -0,0 +1,33 @@
+[gd_resource type="FontFile" load_steps=7 format=3 uid="uid://b0887xnwnkgju"]
+
+[ext_resource type="FontFile" uid="uid://b6jt1itr5jreh" path="res://fonts/DroidSansArabic.ttf" id="1"]
+[ext_resource type="FontFile" uid="uid://cdrxhlo8nqckh" path="res://fonts/DroidSansFallback.ttf" id="2"]
+[ext_resource type="FontFile" uid="uid://7bhkit5l8dka" path="res://fonts/DroidSansHebrew.ttf" id="3"]
+[ext_resource type="FontFile" uid="uid://b74c6j1be4nyv" path="res://fonts/DroidSansJapanese.ttf" id="4"]
+[ext_resource type="FontFile" uid="uid://t73gcvmo33on" path="res://fonts/DroidSansThai.ttf" id="5"]
+[ext_resource type="FontFile" uid="uid://qaejxgrojp2d" path="res://fonts/DroidSans.ttf" id="6"]
+
+[resource]
+fallbacks = Array[Font]([ExtResource("6"), ExtResource("1"), ExtResource("2"), ExtResource("3"), ExtResource("4"), ExtResource("5")])
+face_index = null
+embolden = null
+transform = null
+cache/0/16/0/ascent = 0.0
+cache/0/16/0/descent = 0.0
+cache/0/16/0/underline_position = 0.0
+cache/0/16/0/underline_thickness = 0.0
+cache/0/16/0/scale = 1.0
+cache/0/16/0/glyphs/0/advance = Vector2(0, 0)
+cache/0/16/0/glyphs/0/offset = Vector2(0, 0)
+cache/0/16/0/glyphs/0/size = Vector2(0, 0)
+cache/0/16/0/glyphs/0/uv_rect = Rect2(0, 0, 0, 0)
+cache/0/16/0/glyphs/0/texture_idx = -1
+cache/0/16/0/kerning_overrides/16/0 = Vector2(0, 0)
+cache/0/16/0/kerning_overrides/50/0 = Vector2(0, 0)
+cache/0/50/0/ascent = 0.0
+cache/0/50/0/descent = 0.0
+cache/0/50/0/underline_position = 0.0
+cache/0/50/0/underline_thickness = 0.0
+cache/0/50/0/scale = 1.0
+cache/0/50/0/kerning_overrides/16/0 = Vector2(0, 0)
+cache/0/50/0/kerning_overrides/50/0 = Vector2(0, 0)

+ 0 - 24
gui/translation/hello_en.wav.import

@@ -1,24 +0,0 @@
-[remap]
-
-importer="wav"
-type="AudioStreamWAV"
-uid="uid://d3e12qtu6rlb6"
-path="res://.godot/imported/hello_en.wav-27ed59f2d75c1ba813ab0abd069b6758.sample"
-
-[deps]
-
-source_file="res://hello_en.wav"
-dest_files=["res://.godot/imported/hello_en.wav-27ed59f2d75c1ba813ab0abd069b6758.sample"]
-
-[params]
-
-force/8_bit=false
-force/mono=false
-force/max_rate=false
-force/max_rate_hz=44100
-edit/trim=true
-edit/normalize=true
-edit/loop_mode=0
-edit/loop_begin=0
-edit/loop_end=-1
-compress/mode=0

+ 0 - 24
gui/translation/hello_es.wav.import

@@ -1,24 +0,0 @@
-[remap]
-
-importer="wav"
-type="AudioStreamWAV"
-uid="uid://s18obcimx61r"
-path="res://.godot/imported/hello_es.wav-64fe245556f8642a1881ae257bd123f2.sample"
-
-[deps]
-
-source_file="res://hello_es.wav"
-dest_files=["res://.godot/imported/hello_es.wav-64fe245556f8642a1881ae257bd123f2.sample"]
-
-[params]
-
-force/8_bit=false
-force/mono=false
-force/max_rate=false
-force/max_rate_hz=44100
-edit/trim=true
-edit/normalize=true
-edit/loop_mode=0
-edit/loop_begin=0
-edit/loop_end=-1
-compress/mode=0

+ 0 - 24
gui/translation/hello_jp.wav.import

@@ -1,24 +0,0 @@
-[remap]
-
-importer="wav"
-type="AudioStreamWAV"
-uid="uid://7fh3dentieog"
-path="res://.godot/imported/hello_jp.wav-c31fbd7870b4b969789cb01f208809ac.sample"
-
-[deps]
-
-source_file="res://hello_jp.wav"
-dest_files=["res://.godot/imported/hello_jp.wav-c31fbd7870b4b969789cb01f208809ac.sample"]
-
-[params]
-
-force/8_bit=false
-force/mono=false
-force/max_rate=false
-force/max_rate_hz=44100
-edit/trim=true
-edit/normalize=true
-edit/loop_mode=0
-edit/loop_begin=0
-edit/loop_end=-1
-compress/mode=0

BIN
gui/translation/icon.webp


+ 1 - 1
gui/translation/icon.webp.import

@@ -2,7 +2,7 @@
 
 importer="texture"
 type="CompressedTexture2D"
-uid="uid://brwp8bimc75uu"
+uid="uid://csnnfel8tal41"
 path="res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.ctex"
 metadata={
 "vram_texture": false

BIN
gui/translation/images/flag_japan.webp


+ 4 - 4
gui/translation/speaker.png.import → gui/translation/images/flag_japan.webp.import

@@ -2,16 +2,16 @@
 
 importer="texture"
 type="CompressedTexture2D"
-uid="uid://bbdxdamxifokx"
-path="res://.godot/imported/speaker.png-045bf6684b83b55b088824f14e175d16.ctex"
+uid="uid://b5mub20y1npox"
+path="res://.godot/imported/flag_japan.webp-45f78f2bd7470509154ff093f6e7ec81.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://speaker.png"
-dest_files=["res://.godot/imported/speaker.png-045bf6684b83b55b088824f14e175d16.ctex"]
+source_file="res://images/flag_japan.webp"
+dest_files=["res://.godot/imported/flag_japan.webp-45f78f2bd7470509154ff093f6e7ec81.ctex"]
 
 [params]
 

BIN
gui/translation/images/flag_russia.webp


+ 34 - 0
gui/translation/images/flag_russia.webp.import

@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://leegvlwf2hrn"
+path="res://.godot/imported/flag_russia.webp-db8c7f4fab536218d1b7b7c4b6c2d411.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://images/flag_russia.webp"
+dest_files=["res://.godot/imported/flag_russia.webp-db8c7f4fab536218d1b7b7c4b6c2d411.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1

BIN
gui/translation/images/flag_spain.webp


+ 4 - 4
gui/translation/flag_spain.png.import → gui/translation/images/flag_spain.webp.import

@@ -2,16 +2,16 @@
 
 importer="texture"
 type="CompressedTexture2D"
-uid="uid://dsh7m5tl07jml"
-path="res://.godot/imported/flag_spain.png-fd2012b4e19487cfc4923df0c268553f.ctex"
+uid="uid://c0wh2enemiaay"
+path="res://.godot/imported/flag_spain.webp-f240dac0b8ec15b0721be1d39e3a9520.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://flag_spain.png"
-dest_files=["res://.godot/imported/flag_spain.png-fd2012b4e19487cfc4923df0c268553f.ctex"]
+source_file="res://images/flag_spain.webp"
+dest_files=["res://.godot/imported/flag_spain.webp-f240dac0b8ec15b0721be1d39e3a9520.ctex"]
 
 [params]
 

BIN
gui/translation/images/flag_uk.webp


+ 4 - 4
gui/translation/flag_uk.png.import → gui/translation/images/flag_uk.webp.import

@@ -2,16 +2,16 @@
 
 importer="texture"
 type="CompressedTexture2D"
-uid="uid://cxbco5txqcf40"
-path="res://.godot/imported/flag_uk.png-eb8a2b26ac36f4d0cf0d7345e577ec2c.ctex"
+uid="uid://cy06u7558clgu"
+path="res://.godot/imported/flag_uk.webp-bb99f24470917ddd226648d0bc13ea65.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://flag_uk.png"
-dest_files=["res://.godot/imported/flag_uk.png-eb8a2b26ac36f4d0cf0d7345e577ec2c.ctex"]
+source_file="res://images/flag_uk.webp"
+dest_files=["res://.godot/imported/flag_uk.webp-bb99f24470917ddd226648d0bc13ea65.ctex"]
 
 [params]
 

BIN
gui/translation/images/speaker.webp


+ 4 - 4
gui/translation/flag_japan.png.import → gui/translation/images/speaker.webp.import

@@ -2,16 +2,16 @@
 
 importer="texture"
 type="CompressedTexture2D"
-uid="uid://nokaqfa1grg5"
-path="res://.godot/imported/flag_japan.png-e7284e6af3de26ab9c66cac9c4062038.ctex"
+uid="uid://bk44e7bkr4w4l"
+path="res://.godot/imported/speaker.webp-61e01feddc14193cb3c662b9561152bf.ctex"
 metadata={
 "vram_texture": false
 }
 
 [deps]
 
-source_file="res://flag_japan.png"
-dest_files=["res://.godot/imported/flag_japan.png-e7284e6af3de26ab9c66cac9c4062038.ctex"]
+source_file="res://images/speaker.webp"
+dest_files=["res://.godot/imported/speaker.webp-61e01feddc14193cb3c662b9561152bf.ctex"]
 
 [params]
 

+ 9 - 8
gui/translation/project.godot

@@ -14,7 +14,7 @@ config/name="Translation Demo"
 config/description="A demo showing how Godot seamlessly enables
 the use of localized resources and texts."
 config/tags=PackedStringArray("demo", "internationalization", "official")
-run/main_scene="res://translation_demo.tscn"
+run/main_scene="res://translation_demo_csv.tscn"
 config/features=PackedStringArray("4.2")
 config/icon="res://icon.webp"
 
@@ -26,21 +26,22 @@ window/stretch/aspect="expand"
 [internationalization]
 
 locale/translation_remaps={
-"res://flag_uk.png": PackedStringArray("res://flag_spain.png:es", "res://flag_japan.png:ja"),
-"res://hello_en.wav": PackedStringArray("res://hello_es.wav:es", "res://hello_jp.wav:ja")
+"res://audio/hello_en.wav": PackedStringArray("res://audio/hello_es.wav:es", "res://audio/hello_jp.wav:ja", "res://audio/hello_ru.wav:ru"),
+"res://images/flag_uk.webp": PackedStringArray("res://images/flag_japan.webp:ja", "res://images/flag_russia.webp:ru", "res://images/flag_spain.webp:es")
 }
-locale/translations=PackedStringArray("res://text.en.translation", "res://text.es.translation", "res://text.ja.translation")
+locale/translations=PackedStringArray("res://translations/csv/text.en.translation", "res://translations/csv/text.es.translation", "res://translations/csv/text.ja.translation", "res://translations/csv/text.ru.translation", "res://translations/po/translation_demo_es.po", "res://translations/po/translation_demo_ja.po")
+locale/translations_pot_files=PackedStringArray("res://translation_demo_po.tscn")
 locale/locale_filter_mode=0
 
 [locale]
 
+translations=PackedStringArray("res://TranslationFiles/CSV/text.en.translation", "res://TranslationFiles/CSV/text.es.translation", "res://TranslationFiles/CSV/text.ja.translation", "res://TranslationFiles/CSV/text.ru.translation", "res://TranslationFiles/PO/translation_demo_es.po", "res://TranslationFiles/PO/translation_demo_ja.po")
 translation_remaps={
-"res://flag_uk.png": ["res://flag_spain.png:es", "res://flag_japan.png:ja"],
-"res://hello_en.wav": PackedStringArray("res://hello_es.wav:es", "res://hello_jp.wav:ja")
+"res://Audio/hello_en.wav": PackedStringArray("res://Audio/hello_es.wav:es", "res://Audio/hello_jp.wav:ja", "res://Audio/hello_ru.wav:ru"),
+"res://Images/flag_uk.png": PackedStringArray("res://Images/flag_spain.png:es", "res://Images/flag_japan.png:ja", "res://Images/flag_russia.png:ru")
 }
-translations=PackedStringArray("res://text.en.translation", "res://text.es.translation", "res://text.ja.translation")
+translations_pot_files=PackedStringArray("res://translation_po.gd", "res://translation_demo_po.tscn")
 
 [rendering]
 
 renderer/rendering_method="gl_compatibility"
-renderer/rendering_method.mobile="gl_compatibility"

BIN
gui/translation/screenshots/translation.png


BIN
gui/translation/screenshots/translation.webp


BIN
gui/translation/speaker.png


+ 0 - 4
gui/translation/text.csv

@@ -1,4 +0,0 @@
-KEYS,en,es,ja
-KEY_HELLO,Hello!,Hola!,こんにちは
-KEY_PUSH,Push Me!,Aprétame!,押す
-KEY_TEXT,This is translated!,¡Esto está traducido!,これが翻訳されていました!

+ 0 - 17
gui/translation/text.csv.import

@@ -1,17 +0,0 @@
-[remap]
-
-importer="csv_translation"
-type="Translation"
-uid="uid://dyudr7sc6obqu"
-
-[deps]
-
-files=["res://text.en.translation", "res://text.es.translation", "res://text.ja.translation"]
-
-source_file="res://text.csv"
-dest_files=["res://text.en.translation", "res://text.es.translation", "res://text.ja.translation"]
-
-[params]
-
-compress=true
-delimiter=0

+ 47 - 0
gui/translation/translation_csv.gd

@@ -0,0 +1,47 @@
+# For more information on localization,
+# search Godot's online documentation "Internationalization", or visit
+# https://docs.godotengine.org/en/latest/tutorials/i18n/index.html
+
+extends Panel
+
+func _ready() -> void:
+	_print_intro()
+
+
+func _on_english_pressed() -> void:
+	TranslationServer.set_locale("en")
+	_print_intro()
+
+
+func _on_spanish_pressed() -> void:
+	TranslationServer.set_locale("es")
+	_print_intro()
+
+
+func _on_japanese_pressed() -> void:
+	TranslationServer.set_locale("ja")
+	_print_intro()
+
+
+func _on_russian_pressed() -> void:
+	TranslationServer.set_locale("ru")
+	_print_intro()
+
+
+func _on_play_audio_pressed() -> void:
+	$Audio.play()
+
+
+func _print_intro() -> void:
+	print_rich("\n[b]Language:[/b] %s (%s)" % [TranslationServer.get_locale_name(TranslationServer.get_locale()), TranslationServer.get_locale()])
+
+	# In CSV translation, use the appropriate key in the Object.tr() function to fetch
+	# the corresponding translation.
+	# This is the same for scene nodes containing user-facing texts to be translated.
+	print(tr("KEY_INTRO"))
+
+	# CSV does not support plural translations. If you need pluralization, you must use PO instead.
+
+
+func _on_go_to_po_translation_demo_pressed() -> void:
+	get_tree().change_scene_to_packed(load("res://translation_demo_po.tscn"))

+ 0 - 32
gui/translation/translation_demo.gd

@@ -1,32 +0,0 @@
-extends Control
-
-func _ready() -> void:
-	_set_text_in_label()
-
-
-func _on_english_pressed():
-	TranslationServer.set_locale("en")
-
-
-func _on_spanish_pressed():
-	TranslationServer.set_locale("es")
-
-
-func _on_japanese_pressed():
-	TranslationServer.set_locale("ja")
-
-
-func _on_play_pressed():
-	$Audio.play()
-
-
-func _set_text_in_label():
-	# Use tr(translation_key) to get the desired string in the correct language.
-	var message := "This text is being translated through script: \n"
-	message += tr("KEY_TEXT")
-	$TextLabel.text = message
-
-
-func _notification(what):
-	if what == NOTIFICATION_TRANSLATION_CHANGED:
-		_set_text_in_label()

+ 0 - 131
gui/translation/translation_demo.tscn

@@ -1,131 +0,0 @@
-[gd_scene load_steps=7 format=3 uid="uid://7bhrbgdbrped"]
-
-[ext_resource type="Script" path="res://translation_demo.gd" id="1"]
-[ext_resource type="FontVariation" uid="uid://duo4ycm3e6mrb" path="res://font/droid_sans.tres" id="2_fnagj"]
-[ext_resource type="Texture2D" uid="uid://bbdxdamxifokx" path="res://speaker.png" id="3"]
-[ext_resource type="Texture2D" uid="uid://cxbco5txqcf40" path="res://flag_uk.png" id="4"]
-[ext_resource type="AudioStream" uid="uid://d3e12qtu6rlb6" path="res://hello_en.wav" id="5"]
-
-[sub_resource type="Theme" id="Theme_2nqf7"]
-default_font = ExtResource("2_fnagj")
-default_font_size = 0
-
-[node name="TranslationDemo" type="Control"]
-layout_mode = 3
-anchors_preset = 8
-anchor_left = 0.5
-anchor_top = 0.5
-anchor_right = 0.5
-anchor_bottom = 0.5
-offset_left = -512.0
-offset_top = -300.0
-offset_right = 512.0
-offset_bottom = 300.0
-size_flags_horizontal = 2
-size_flags_vertical = 2
-theme = SubResource("Theme_2nqf7")
-script = ExtResource("1")
-
-[node name="English" type="Button" parent="."]
-layout_mode = 0
-offset_left = 32.0
-offset_top = 64.0
-offset_right = 192.0
-offset_bottom = 88.0
-size_flags_horizontal = 2
-size_flags_vertical = 2
-text = "Use English"
-
-[node name="Spanish" type="Button" parent="."]
-layout_mode = 0
-offset_left = 32.0
-offset_top = 112.0
-offset_right = 192.0
-offset_bottom = 136.0
-size_flags_horizontal = 2
-size_flags_vertical = 2
-text = "Use Spanish"
-
-[node name="Japanese" type="Button" parent="."]
-layout_mode = 0
-offset_left = 32.0
-offset_top = 160.0
-offset_right = 192.0
-offset_bottom = 184.0
-size_flags_horizontal = 2
-size_flags_vertical = 2
-text = "Use Japanese"
-
-[node name="Description" type="Label" parent="."]
-layout_mode = 0
-offset_left = 243.0
-offset_top = 42.0
-offset_right = 804.0
-offset_bottom = 312.0
-size_flags_horizontal = 2
-size_flags_vertical = 0
-text = "This is a demo of how a game can be internationalized.
-Translations are created in a CSV file and then imported into Godot.
-
-Using a TTF/OTF font with CJK is required for this demo to run. One is provided
-in the font/ folder that you can use for your games.
-
-Godot allows internationalized text to change automatically when the locale is
-modified. Resources can also be set internationalized alternatives and replaced
-automatically on locale change."
-
-[node name="HSeparator" type="HSeparator" parent="."]
-layout_mode = 0
-offset_left = 33.0
-offset_top = 330.0
-offset_right = 1001.0
-offset_bottom = 370.0
-
-[node name="HelloText" type="Label" parent="."]
-layout_mode = 0
-offset_left = 246.0
-offset_top = 381.0
-offset_right = 324.0
-offset_bottom = 400.0
-size_flags_vertical = 0
-text = "KEY_HELLO"
-
-[node name="PlayAudio" type="Button" parent="."]
-layout_mode = 0
-offset_left = 243.0
-offset_top = 442.0
-offset_right = 475.0
-offset_bottom = 467.0
-text = "KEY_PUSH"
-icon = ExtResource("3")
-
-[node name="Flag" type="TextureRect" parent="."]
-layout_mode = 0
-offset_left = 85.0
-offset_top = 382.0
-offset_right = 213.0
-offset_bottom = 467.0
-texture = ExtResource("4")
-
-[node name="Audio" type="AudioStreamPlayer" parent="."]
-stream = ExtResource("5")
-
-[node name="TextLabel" type="Label" parent="."]
-layout_mode = 0
-anchor_left = 0.5
-anchor_top = 0.5
-anchor_right = 0.5
-anchor_bottom = 0.5
-offset_left = 21.0
-offset_top = 80.0
-offset_right = 487.0
-offset_bottom = 255.0
-grow_horizontal = 2
-grow_vertical = 2
-text = "This text is being translated through script:
-"
-
-[connection signal="pressed" from="English" to="." method="_on_english_pressed"]
-[connection signal="pressed" from="Spanish" to="." method="_on_spanish_pressed"]
-[connection signal="pressed" from="Japanese" to="." method="_on_japanese_pressed"]
-[connection signal="pressed" from="PlayAudio" to="." method="_on_play_pressed"]

+ 144 - 0
gui/translation/translation_demo_csv.tscn

@@ -0,0 +1,144 @@
+[gd_scene load_steps=6 format=3 uid="uid://du3apufm66p3x"]
+
+[ext_resource type="Script" path="res://translation_csv.gd" id="1_o1a7r"]
+[ext_resource type="Texture2D" uid="uid://bk44e7bkr4w4l" path="res://images/speaker.webp" id="3_d0i3f"]
+[ext_resource type="FontFile" uid="uid://b0887xnwnkgju" path="res://fonts/droid_sans.tres" id="3_wf1ar"]
+[ext_resource type="Texture2D" uid="uid://cy06u7558clgu" path="res://images/flag_uk.webp" id="4_xn1dg"]
+[ext_resource type="AudioStream" uid="uid://ciept8j0x21to" path="res://audio/hello_en.wav" id="6_a303u"]
+
+[node name="TranslationDemoCSV" type="Panel"]
+anchors_preset = 8
+anchor_left = 0.5
+anchor_top = 0.5
+anchor_right = 0.5
+anchor_bottom = 0.5
+offset_left = -512.0
+offset_top = -300.0
+offset_right = 512.0
+offset_bottom = 300.0
+size_flags_horizontal = 2
+size_flags_vertical = 2
+script = ExtResource("1_o1a7r")
+
+[node name="Title" type="Label" parent="."]
+layout_mode = 0
+offset_left = 422.0
+offset_top = 12.0
+offset_right = 602.0
+offset_bottom = 49.0
+theme_override_colors/font_color = Color(0.682353, 1, 0.65098, 1)
+theme_override_font_sizes/font_size = 24
+text = "CSV Example"
+
+[node name="English" type="Button" parent="."]
+layout_mode = 0
+offset_left = 32.0
+offset_top = 81.9594
+offset_right = 192.0
+offset_bottom = 105.959
+size_flags_horizontal = 2
+size_flags_vertical = 2
+text = "Use English"
+
+[node name="Spanish" type="Button" parent="."]
+layout_mode = 0
+offset_left = 32.0
+offset_top = 129.959
+offset_right = 192.0
+offset_bottom = 153.959
+size_flags_horizontal = 2
+size_flags_vertical = 2
+text = "Use Spanish"
+
+[node name="Japanese" type="Button" parent="."]
+layout_mode = 0
+offset_left = 32.0
+offset_top = 177.959
+offset_right = 192.0
+offset_bottom = 201.959
+size_flags_horizontal = 2
+size_flags_vertical = 2
+text = "Use Japanese"
+
+[node name="Russian" type="Button" parent="."]
+layout_mode = 0
+offset_left = 32.0
+offset_top = 225.959
+offset_right = 192.0
+offset_bottom = 249.959
+size_flags_horizontal = 2
+size_flags_vertical = 2
+text = "Use Russian"
+
+[node name="Description" type="Label" parent="."]
+layout_mode = 0
+offset_left = 243.0
+offset_top = 59.9594
+offset_right = 804.0
+offset_bottom = 329.959
+size_flags_horizontal = 2
+size_flags_vertical = 0
+text = "This is a demo of how a project can be internationalized.
+Translations are created in a CSV file and then imported into Godot.
+
+For correct display, the font used must contain the glyphs required by the target language.
+See the \"fonts\" folder for some fonts that you can use in your project.
+Godot can load system fonts as a fallback, but this is not supported on all platforms
+and the different visual design of system fonts can create inconsistencies.
+
+Godot allows internationalized text to change automatically when the locale is
+modified. Resources can also be set to internationalized alternatives and replaced
+automatically on locale change. This process is known as remapping."
+
+[node name="HSeparator" type="HSeparator" parent="."]
+layout_mode = 0
+offset_left = 33.0
+offset_top = 354.0
+offset_right = 1001.0
+offset_bottom = 394.0
+
+[node name="HelloText" type="Label" parent="."]
+layout_mode = 0
+offset_left = 246.0
+offset_top = 405.0
+offset_right = 326.0
+offset_bottom = 429.0
+size_flags_vertical = 0
+theme_override_fonts/font = ExtResource("3_wf1ar")
+text = "KEY_HELLO"
+
+[node name="PlayAudio" type="Button" parent="."]
+layout_mode = 0
+offset_left = 243.0
+offset_top = 466.0
+offset_right = 475.0
+offset_bottom = 498.0
+theme_override_fonts/font = ExtResource("3_wf1ar")
+text = "KEY_PUSH"
+icon = ExtResource("3_d0i3f")
+
+[node name="Flag" type="TextureRect" parent="."]
+layout_mode = 0
+offset_left = 85.0
+offset_top = 406.0
+offset_right = 213.0
+offset_bottom = 491.0
+texture = ExtResource("4_xn1dg")
+
+[node name="Audio" type="AudioStreamPlayer2D" parent="."]
+stream = ExtResource("6_a303u")
+
+[node name="GoToPOTranslationDemo" type="Button" parent="."]
+layout_mode = 0
+offset_left = 761.0
+offset_top = 545.0
+offset_right = 1000.0
+offset_bottom = 576.0
+text = "Go to PO Translation Demo"
+
+[connection signal="pressed" from="English" to="." method="_on_english_pressed"]
+[connection signal="pressed" from="Spanish" to="." method="_on_spanish_pressed"]
+[connection signal="pressed" from="Japanese" to="." method="_on_japanese_pressed"]
+[connection signal="pressed" from="Russian" to="." method="_on_russian_pressed"]
+[connection signal="pressed" from="PlayAudio" to="." method="_on_play_audio_pressed"]
+[connection signal="pressed" from="GoToPOTranslationDemo" to="." method="_on_go_to_po_translation_demo_pressed"]

+ 130 - 0
gui/translation/translation_demo_po.tscn

@@ -0,0 +1,130 @@
+[gd_scene load_steps=6 format=3 uid="uid://u6cnwv1b1mhl"]
+
+[ext_resource type="Script" path="res://translation_po.gd" id="1_u1syg"]
+[ext_resource type="FontFile" uid="uid://b0887xnwnkgju" path="res://fonts/droid_sans.tres" id="3_0g48e"]
+[ext_resource type="Texture2D" uid="uid://bk44e7bkr4w4l" path="res://images/speaker.webp" id="3_x3031"]
+[ext_resource type="Texture2D" uid="uid://cy06u7558clgu" path="res://images/flag_uk.webp" id="4_2she1"]
+[ext_resource type="AudioStream" uid="uid://ciept8j0x21to" path="res://audio/hello_en.wav" id="6_v8u3c"]
+
+[node name="TranslationDemoPO" type="Panel"]
+anchors_preset = 8
+anchor_left = 0.5
+anchor_top = 0.5
+anchor_right = 0.5
+anchor_bottom = 0.5
+offset_left = -512.0
+offset_top = -300.0
+offset_right = 512.0
+offset_bottom = 300.0
+size_flags_horizontal = 2
+size_flags_vertical = 2
+script = ExtResource("1_u1syg")
+
+[node name="Title" type="Label" parent="."]
+layout_mode = 0
+offset_left = 422.0
+offset_top = 12.0
+offset_right = 602.0
+offset_bottom = 50.0
+theme_override_colors/font_color = Color(0.788235, 0.54902, 0.933333, 1)
+theme_override_font_sizes/font_size = 24
+text = "PO Example"
+
+[node name="English" type="Button" parent="."]
+layout_mode = 0
+offset_left = 32.0
+offset_top = 81.592
+offset_right = 192.0
+offset_bottom = 112.592
+size_flags_horizontal = 2
+size_flags_vertical = 2
+text = "Use English"
+
+[node name="Spanish" type="Button" parent="."]
+layout_mode = 0
+offset_left = 32.0
+offset_top = 129.592
+offset_right = 192.0
+offset_bottom = 160.592
+size_flags_horizontal = 2
+size_flags_vertical = 2
+text = "Use Spanish"
+
+[node name="Japanese" type="Button" parent="."]
+layout_mode = 0
+offset_left = 32.0
+offset_top = 177.592
+offset_right = 192.0
+offset_bottom = 208.592
+size_flags_horizontal = 2
+size_flags_vertical = 2
+text = "Use Japanese"
+
+[node name="Description" type="Label" parent="."]
+layout_mode = 0
+offset_left = 243.0
+offset_top = 64.592
+offset_right = 929.0
+offset_bottom = 334.592
+size_flags_horizontal = 2
+size_flags_vertical = 0
+text = "This second demo showcases localization using gettext (PO/POT) files.
+
+The resouce remapping process is the same with CSV. The in-game text translation
+process is also the same – use keys to fetch the appropriate translation.
+
+The main difference between PO files and CSV files is the way both of them store
+the translated data in their files.  Have a look at the \"translations/po\"
+and \"translations/csv\" folders to see the files involved."
+
+[node name="HSeparator" type="HSeparator" parent="."]
+layout_mode = 0
+offset_left = 33.0
+offset_top = 354.0
+offset_right = 1001.0
+offset_bottom = 394.0
+
+[node name="HelloText" type="Label" parent="."]
+layout_mode = 0
+offset_left = 246.0
+offset_top = 405.0
+offset_right = 325.0
+offset_bottom = 429.0
+size_flags_vertical = 0
+theme_override_fonts/font = ExtResource("3_0g48e")
+text = "Hello!"
+
+[node name="PlayAudio" type="Button" parent="."]
+layout_mode = 0
+offset_left = 243.0
+offset_top = 466.0
+offset_right = 475.0
+offset_bottom = 498.0
+theme_override_fonts/font = ExtResource("3_0g48e")
+text = "Push Me!"
+icon = ExtResource("3_x3031")
+
+[node name="Flag" type="TextureRect" parent="."]
+layout_mode = 0
+offset_left = 85.0
+offset_top = 406.0
+offset_right = 213.0
+offset_bottom = 491.0
+texture = ExtResource("4_2she1")
+
+[node name="Audio" type="AudioStreamPlayer2D" parent="."]
+stream = ExtResource("6_v8u3c")
+
+[node name="GoToCSVTranslationDemo" type="Button" parent="."]
+layout_mode = 0
+offset_left = 761.0
+offset_top = 545.0
+offset_right = 1000.0
+offset_bottom = 576.0
+text = "Go to CSV Translation Demo"
+
+[connection signal="pressed" from="English" to="." method="_on_english_pressed"]
+[connection signal="pressed" from="Spanish" to="." method="_on_spanish_pressed"]
+[connection signal="pressed" from="Japanese" to="." method="_on_japanese_pressed"]
+[connection signal="pressed" from="PlayAudio" to="." method="_on_play_audio_pressed"]
+[connection signal="pressed" from="GoToCSVTranslationDemo" to="." method="_on_go_to_csv_translation_demo_pressed"]

+ 44 - 0
gui/translation/translation_po.gd

@@ -0,0 +1,44 @@
+# For more information on translation using PO files,
+# search Godot's online documentation "Localization using gettext", or visit
+# https://docs.godotengine.org/en/latest/tutorials/i18n/localization_using_gettext.html
+
+extends Panel
+
+func _ready() -> void:
+	_print_intro()
+
+func _on_english_pressed() -> void:
+	TranslationServer.set_locale("en")
+	_print_intro()
+
+
+func _on_spanish_pressed() -> void:
+	TranslationServer.set_locale("es")
+	_print_intro()
+
+
+func _on_japanese_pressed() -> void:
+	TranslationServer.set_locale("ja")
+	_print_intro()
+
+
+func _on_play_audio_pressed() -> void:
+	$Audio.play()
+
+
+func _print_intro() -> void:
+	print_rich("\n[b]Language:[/b] %s (%s)" % [TranslationServer.get_locale_name(TranslationServer.get_locale()), TranslationServer.get_locale()])
+
+	# In PO translation, you would use source string as the 'key' for the Object.tr() function.
+	# This is the same for scene nodes containing user-facing texts to be translated.
+	print(tr("Hello, this is a translation demo project."))
+
+	# PO plural translation example.
+	# The difference with CSV is that you must add the "plural_message" argument, because PO files
+	# expect the data (else undefine behaviour might occur).
+	var days_passed := randi_range(1, 3)
+	print(tr_n("One day ago.", "{days} days ago.", days_passed).format({ days = days_passed }))
+
+
+func _on_go_to_csv_translation_demo_pressed() -> void:
+	get_tree().change_scene_to_packed(load("res://translation_demo_csv.tscn"))

+ 4 - 0
gui/translation/translations/csv/text.csv

@@ -0,0 +1,4 @@
+,en,es,ja,ru
+KEY_HELLO,Hello!,Hola!,こんにちは!,Привет!
+KEY_PUSH,Push Me!,Aprétame!,押す!,Толкни меня!
+KEY_INTRO,"Hello, this is a translation demo project.","Hola, este es un proyecto de demostración de traducción.","こんにちは、これは翻訳デモプロジェクトです.","Здравствуйте, это демонстрационный проект перевода."

+ 17 - 0
gui/translation/translations/csv/text.csv.import

@@ -0,0 +1,17 @@
+[remap]
+
+importer="csv_translation"
+type="Translation"
+uid="uid://ftws6mo13r10"
+
+[deps]
+
+files=["res://translations/csv/text.en.translation", "res://translations/csv/text.es.translation", "res://translations/csv/text.ja.translation", "res://translations/csv/text.ru.translation"]
+
+source_file="res://translations/csv/text.csv"
+dest_files=["res://translations/csv/text.en.translation", "res://translations/csv/text.es.translation", "res://translations/csv/text.ja.translation", "res://translations/csv/text.ru.translation"]
+
+[params]
+
+compress=true
+delimiter=0

+ 56 - 0
gui/translation/translations/po/translation_demo.pot

@@ -0,0 +1,56 @@
+# LANGUAGE translation for Translation Demo for the following files:
+# res://translation_po.gd
+# res://translation_demo_po.tscn
+#
+#
+# FIRST AUTHOR < EMAIL @ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Translation Demo\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+#: translation_demo_po.tscn
+msgid "Hello, this is a translation demo project."
+msgstr ""
+
+#: translation_demo_po.tscn
+msgid "One day ago."
+msgid_plural "{days} days ago."
+msgstr[0] ""
+msgstr[1] ""
+
+#: translation_demo_po.tscn
+msgid "Use English"
+msgstr ""
+
+#: translation_demo_po.tscn
+msgid "Use Spanish"
+msgstr ""
+
+#: translation_demo_po.tscn
+msgid "Use Japanese"
+msgstr ""
+
+#: translation_demo_po.tscn
+msgid "This second demo shows translation using PO files. "
+""
+"The resouce remapping process is the same with CSV. The in-game text translation "
+"process is also the same - use keys to fetch the appropriate translation."
+""
+"The main difference between PO files and CSV files is the way both of them store "
+"the translated data in their files.  Have a look at "TranslationFiles/PO" folder "
+"and "TranslationFiles/CSV" folder to see the files involved in translation."
+""
+"To find out more about PO files, search Godot's online documentation "Localization using gettext""
+msgstr ""
+
+#: translation_demo_po.tscn
+msgid "Hello!"
+msgstr ""
+
+#: translation_demo_po.tscn
+msgid "Push Me!"
+msgstr ""

+ 62 - 0
gui/translation/translations/po/translation_demo_es.po

@@ -0,0 +1,62 @@
+# LANGUAGE translation for Translation Demo for the following files:
+# res://translation_po.gd
+# res://translation_demo_po.tscn
+#
+#
+# FIRST AUTHOR < EMAIL @ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Translation Demo\n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 2.3.1\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: translation_demo_po.tscn
+msgid "Hello, this is a translation demo project."
+msgstr "Hola, este es un proyecto de demostración de traducción."
+
+#: translation_demo_po.tscn
+msgid "One day ago."
+msgid_plural "{days} days ago."
+msgstr[0] "Hace un dia."
+msgstr[1] "Hach {days} dias."
+
+#: translation_demo_po.tscn
+msgid "Use English"
+msgstr ""
+
+#: translation_demo_po.tscn
+msgid "Use Spanish"
+msgstr ""
+
+#: translation_demo_po.tscn
+msgid "Use Japanese"
+msgstr ""
+
+#: translation_demo_po.tscn
+msgid ""
+"This second demo shows translation using PO files. The resouce remapping "
+"process is the same with CSV. The in-game text translation process is also "
+"the same - use keys to fetch the appropriate translation.The main difference "
+"between PO files and CSV files is the way both of them store the translated "
+"data in their files.  Have a look at \"TranslationFiles/PO\" folder and "
+"\"TranslationFiles/CSV\" folder to see the files involved in translation.To "
+"find out more about PO files, search Godot's online documentation "
+"\"Localization using gettext\""
+msgstr ""
+
+#: translation_demo_po.tscn
+msgid "Hello!"
+msgstr "Hola!"
+
+#: translation_demo_po.tscn
+msgid "Push Me!"
+msgstr "Aprétame!"

+ 61 - 0
gui/translation/translations/po/translation_demo_ja.po

@@ -0,0 +1,61 @@
+# LANGUAGE translation for Translation Demo for the following files:
+# res://translation_po.gd
+# res://translation_demo_po.tscn
+#
+#
+# FIRST AUTHOR < EMAIL @ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Translation Demo\n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 2.3.1\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: translation_demo_po.tscn
+msgid "Hello, this is a translation demo project."
+msgstr "こんにちは、これは翻訳デモプロジェクトです."
+
+#: translation_demo_po.tscn
+msgid "One day ago."
+msgid_plural "{days} days ago."
+msgstr[0] "{days}日前."
+
+#: translation_demo_po.tscn
+msgid "Use English"
+msgstr ""
+
+#: translation_demo_po.tscn
+msgid "Use Spanish"
+msgstr ""
+
+#: translation_demo_po.tscn
+msgid "Use Japanese"
+msgstr ""
+
+#: translation_demo_po.tscn
+msgid ""
+"This second demo shows translation using PO files. The resouce remapping "
+"process is the same with CSV. The in-game text translation process is also "
+"the same - use keys to fetch the appropriate translation.The main difference "
+"between PO files and CSV files is the way both of them store the translated "
+"data in their files.  Have a look at \"TranslationFiles/PO\" folder and "
+"\"TranslationFiles/CSV\" folder to see the files involved in translation.To "
+"find out more about PO files, search Godot's online documentation "
+"\"Localization using gettext\""
+msgstr ""
+
+#: translation_demo_po.tscn
+msgid "Hello!"
+msgstr "こんにちは!"
+
+#: translation_demo_po.tscn
+msgid "Push Me!"
+msgstr "押す!"