Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Ukrainian and Russian localizations #344

Merged
merged 2 commits into from
Dec 21, 2023
Merged

Conversation

ghost
Copy link

@ghost ghost commented Dec 21, 2023

So, several things:

  1. I added 2 new localizations: Ukrainian and Russian
  2. I done small fix to your code related to list of available languages. Instead of being hard-coded array, it now get list from translation server directly, so if you need add new translation to program - them add translation file to translation tab in project settings and then you done.
  3. Please, I STRONGLY recommend you to move your translations from csv "system" to gettext (here Godot docs: https://docs.godotengine.org/en/stable/tutorials/i18n/localization_using_gettext.html). Adding and updating existing translations in csv file (especially when ALL translations inside single file...) is pure nightmare. gettext is system designed specifically for translation and localization needs, and Godot introduced support for it in 4. So, again, please, consider using it instead... If you have questions about gettext, I might help.
  4. I think you might want to add warning to "Wrap Mouse" tooltip, that currently this function WOULDN'T work on Linux under Wayland (so add something like this to tooltip: "Note: this feature might not work under Linux + Wayland." or something) since you shouldn't be able to move cursor around there. This might change once native Wayland support will be added to Godot (most likely in 4.3, you can check progress here: Add Wayland support godotengine/godot#86180) but I can't tell.
  5. Once you might decide to move to gettext, it will be good time to refactor you translations a bit: don't expose bindings to translators. Expose it like this: "{shortcut_dublicate}: Duplicates the selected tags" which you would replace at runtime.

So, as for main part of this PR: it seems that I didn't broken anything. I tested both translations and in overall it looks good. I might missed some typos here and there, but in overall it usable.

@MewPurPur
Copy link
Owner

Thanks! I also obviously approve of the change with the TranslationServer, anything that reduces the required maintenance without downsides is super welcome :P

Please, I STRONGLY recommend you to move your translations from csv "system" to gettext (here Godot docs: https://docs.godotengine.org/en/stable/tutorials/i18n/localization_using_gettext.html). Adding and updating existing translations in csv file (especially when ALL translations inside single file...) is pure nightmare. gettext is system designed specifically for translation and localization needs, and Godot introduced support for it in 4. So, again, please, consider using it instead... If you have questions about gettext, I might help.

Once you might decide to move to gettext, it will be good time to refactor you translations a bit: don't expose bindings to translators. Expose it like this: "{shortcut_dublicate}: Duplicates the selected tags" which you would replace at runtime.

You seem knowledgeable about this. Could you please make an issue about how to improve the translation system, especially if you can go into detail about the implementation and what makes it superior?

I think you might want to add warning to "Wrap Mouse" tooltip, that currently this function WOULDN'T work on Linux under Wayland (so add something like this to tooltip: "Note: this feature might not work under Linux + Wayland." or something) since you shouldn't be able to move cursor around there. This might change once native Wayland support will be added to Godot (most likely in 4.3, you can check progress here: godotengine/godot#86180) but I can't tell.

A warning was on my radar already, as the setting also can't work for web, I think. I'm going to need to find some way to test out if it works, and some way to display a warning in the setting. Not too trivial, so please make an issue, especially if you can think of the implementation details.

@MewPurPur
Copy link
Owner

MewPurPur commented Dec 21, 2023

Also, how do you want to be mentioned in AUTHORS.md? Do you want to have a real name or do you only want to be listed by your GitHub handle?

@ghost
Copy link
Author

ghost commented Dec 21, 2023

As for credits, using "Volkov" is fine. If you wish, you can leave my contact email "[email protected]" (which I usually leave in software that I translated in case of feedback) in case someone might have questions about my translations or they have suggestions to make it better.

A warning was on my radar already, as the setting also can't work for web, I think. I'm going to need to find some way to test out if it works, and some way to display a warning in the setting. Not too trivial, so please make an issue, especially if you can think of the implementation details.

Well, I have one untested idea, so you can check in spare time:
When user opens options menu (where they can turn on/off wrap mode) and try to forcefully move cursor to somewhere and immediately (or maybe with some delay) after that check if cursor stays on that coordinate that you specified (in pseudo code):

cursor_next_position = current_pos + 100
cursor_pos = cursor_next_position
if cursor_pos == cursor_next_position:
    current platform supports cursor moving!
else:
   current platform doesn't support cursor moving.

(also, make sure to call this function ONLY once, don't call it again every time when user opens options menu)

This might work, but I will consider that to be dirty hack. Maybe someone could open proposal to godot to add function to check if platform allow cursor moving?

You seem knowledgeable about this. Could you please make an issue about how to improve the translation system, especially if you can go into detail about the implementation and what makes it superior?

(yeah, because I kinda of translator myself, you can check my profile and found that I often do software translations, especially GTK4 software that by default uses gettext system. Hence that how I learned about gettext and why people should use it instead of their csv/ini/etc formats.)

I might even make pull request that will convert your csv to gettext, once I will have energy to do so. But TLDR: gettext (https://www.gnu.org/software/gettext/) is old, like around 40 years old. It was designed specifically in software translation in mind. And for this almost 40 years, gettext become standard. There many web translations service (like weblate, and you will see that they will support gettext.) or offline tools (arguably the best one is free and open source POEditor https://poeditor.com/) was made.

Selling point of gettext:

  • pluralization (if you have goal to implement something like: "User picked 1 file" and "User picked 10 files" and you want this feature to work across any language that has pluralization, then gettext got you covered.
  • As I mentioned, standardization. So you can found tools to work with this format that available for many programming languages, toolkits, engines, etc.
  • More superior distribution model between you and your translator. As name suggest, gettext gets texts that need to be translated directly from your source scripts/source files. You will need to specify which scripts it need to collect from (or, in case of Godot, you can even specify scene files and some other resources) and then generate POT file, that translators will use for their translations. here example:
func _onready():
    var a: string = tr("Good morning, {user_name}!", "Welcome User Message")
    print(a)

Then go to project setting, to localization tab and then there you will see "POT generation": here you will provide what scripts and projects that you want to add and click Generate POT, which will prompt godot to save you somewhere pot file.

Code above will produce something like this:

#: path/to/script.gd
msgctxt "Welcome User Message"
msgid "Good morning, {user_name}!"
msgstr ""

Where #: and path is where this string used (that it, if you will use same string with same context in several scripts, there will be several patches. If will allow translators to quickly open exactly source line where this strings will be used, so if they can't get context - they can try to guess it from your code. Also, you can do same to quickly found all scripts where particular string is used, which will make refactoring localization easier.)
msgctxt is context. It's used to differentiate 2 same string that might have different meaning. From example of godot wiki:
in english word "close" might be used as "Close door and "I'm close to something". With context hint, this 2 words become 2 separate entries. Also, this context help used to sort string by context in software such as POeditor, which is just neat QoL feature that you translator will appreciate if you will provide good context hints.
msgid - is id for message, as you might used in csv: #warp_method_tooltip but instead entire source sentence!
msgstr - translated string that your translator will be required to fill.

This means, that you can store translations in your code whatever you want: arrays, dictionaries, any other data format, whatever, your user will still get POT file that will always look same for them.

And since entire source string used as identifier, it's mean that once you will change, that ID in every other language AUTOMATICALLY become "fuzzy" or in other words, outdated and will NOT be used. So, if we would our "a" string declaration to something like this:
var a: string = tr("Good evening, {user_name}!", "Welcome User Message")
And you will generate new pot file, will show "Good evening, {user_name}!" with any language, because your ID string will be used as fallback! And it will be as this until translator will update strings in their own translations!

In csv there is no such option: your program will still try to load same key if translation file has one. So if translators didn't catch up or you won't manually remove outdated strings from their translations or simple change key manually - program will still use old string, that most likely will be 100% incorrect at that point.

Also, with csv you need to ask translators or provide some script/tool to merge newly added strings with outdated translations, otherwise it will be hard to keep track for your translators of what was added and what doesn't.

In gettext, you have merge tools. POEditor even has button for this, where you open translation file, pick "Update from POT", pick newly generated POT file and it will be merged with translation. All outdated strings will be marked as outdated or removed. Strings that need slight modifications will be marked as such. And as you can see, there no invention from your side here, except to generate POT file (which is so easy to do, that your translators can do that themself without any troubles, if they wish). So much easier then dealing with csv files.

  • It's easy to mark string as "not ready" so if translator unsure about it, if will still stay in file, but your game/software will ignore it and will show fallback text instead. With csv you don't really have such choice.
  • gettext support ability to extract comments that specifically made for translators using: # TRANSLATORS: keyword, but sadly, this feature not implemented on Godot's side: Add support for generating comments from tr() and tr_n() functions for gettext (pot) translation system  godotengine/godot-proposals#8555, but might be in future. This can be used to warn translators about some limitations (hey, this string shouldn't be longer then 10 symbols or game will crash!) or in detailed manner explain something.
  • There also option for per-translation comments that translators can leave in their translations for others, to explain why they did some translations choices. Software such as POEditor will show such comments in special window.
  • software that implements gettext (such as, again, POEditor) usually also implements "translation memory" feature, that allow you to store translations that you made with that program, so in future it will start suggesting you translations to similar strings that you translated in past, which is really nice feature since you can't always remember yourself how you translated some term in past.
  • Much more VCS friendly (so easier to review translation changes from your translators).
  • And, just in general, it's much easier and simpler to work with specialized software, then dealing with some hack-ish csv files that might easy fall apart on first refactor and harder to maintain.

The only real downside that even wiki mention, is that gettext might be slightly harder to grasp. And while you absolutely can edit po files by hand/text editors, it's recommended to use specialized software such as... (how much times I mentioned it?) Poeditor. So you might want to provide some documentation "how to translate my program" (which you should do anyway, but difference is that gettext docs might be slightly longer) where you will be practically required to ask translator to download that software.

There probably other points that I forget to mention, but, in general, that's it.

@MewPurPur
Copy link
Owner

I opened an issue for the first thing. If you don't want to open an issue about translations, I can do it too, but I feel like you'd know how to detail things better.

@MewPurPur MewPurPur merged commit eed61f5 into MewPurPur:main Dec 21, 2023
@MewPurPur
Copy link
Owner

Thanks!

@Riteo
Copy link

Riteo commented Dec 22, 2023

I think you might want to add warning to "Wrap Mouse" tooltip, that currently this function WOULDN'T work on Linux under Wayland (so add something like this to tooltip: "Note: this feature might not work under Linux + Wayland." or something) since you shouldn't be able to move cursor around there. This might change once native Wayland support will be added to Godot (most likely in 4.3, you can check progress here: godotengine/godot#86180) but I can't tell.

FTR, mouse warping works on the Wayland backend like in many native applications. As you noted it's not guaranteed by the spec, but it works in most compositors and it's a common hack.

I'm planning to propose a protocol change myself.

There's a tracker for this issue on the wayland-protocols repo if you're interested: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/158

MewPurPur pushed a commit that referenced this pull request Jun 1, 2024
MewPurPur pushed a commit that referenced this pull request Jun 1, 2024
MewPurPur pushed a commit that referenced this pull request Jun 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants