Improve CSV translations

- Adds context and plural support
- Adds unescape import options
- Better document OptimizedTranslation

Co-Authored-By: Pāvels Nadtočajevs <7645683+bruvzg@users.noreply.github.com>
This commit is contained in:
Haoyu Qiu
2025-10-24 12:00:03 +08:00
parent 0fdb93cde6
commit c1ee8e52e4
5 changed files with 218 additions and 65 deletions

View File

@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="OptimizedTranslation" inherits="Translation" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
An optimized translation, used by default for CSV Translations.
An optimized translation.
</brief_description>
<description>
An optimized translation, used by default for CSV Translations. Uses real-time compressed translations, which results in very small dictionaries.
An optimized translation. Uses real-time compressed translations, which results in very small dictionaries.
This class does not store the untranslated strings for optimization purposes. Therefore, [method Translation.get_message_list] always returns an empty array, and [method Translation.get_message_count] always returns [code]0[/code].
</description>
<tutorials>
</tutorials>
@ -14,6 +15,7 @@
<param index="0" name="from" type="Translation" />
<description>
Generates and sets an optimized translation from the given [Translation] resource.
[b]Note:[/b] Messages in [param from] should not use context or plural forms.
[b]Note:[/b] This method is intended to be used in the editor. It does nothing when called from an exported project.
</description>
</method>

View File

@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ResourceImporterCSVTranslation" inherits="ResourceImporter" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Imports comma-separated values
Imports comma-separated values as [Translation]s.
</brief_description>
<description>
Comma-separated values are a plain text table storage format. The format's simplicity makes it easy to edit in any text editor or spreadsheet software. This makes it a common choice for game localization.
In the CSV file used for translation, the first column contains string identifiers, and the first row serves as the header. The first column's header can be any value. The remaining headers indicate the locale for that column. Columns whose headers begin with an underscore ([code]_[/code]) will be ignored.
[b]Example CSV file:[/b]
[codeblock lang=text]
keys,en,es,ja
@ -13,16 +14,38 @@
BYE,Goodbye,Adiós,さようなら
QUOTE,"""Hello"" said the man.","""Hola"" dijo el hombre.",「こんにちは」男は言いました
[/codeblock]
Although keys in the first column typically use uppercase string identifiers, it is not uncommon to directly use strings appearing in the game as keys. To avoid string ambiguity, you can use a special [code]?context[/code] column to specify the context to use with [method Object.tr].
[codeblock lang=text]
en,?context,fr,ja,zh
Letter,Alphabet,Lettre,字母,字母
Letter,Message,Courrier,手紙,信件
[/codeblock]
To set the plural form of a string to use with [method Object.tr_n], add a special [code]?plural[/code] column. After setting the plural form of the source string in this column, you can add additional rows to provide translations for more plural forms. The first column and all special columns in these plural form rows must be empty.
Godot includes built-in plural rules for some languages. You can also customize them using a special [code]?pluralrule[/code] row. See [url=https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html]GNU gettext[/url] for examples and more info.
[codeblock lang=text]
en,?plural,fr,ru,zh,_Comment
?pluralrule,,nplurals=2; plural=(n &gt;= 2);,,,Customize the plural rule for French
There is %d apple,There are %d apples,Il y a %d pomme,Есть %d яблоко,那里有%d个苹果,
,,Il y a %d pommes,Есть %d яблока,,
,,,Есть %d яблок,,
[/codeblock]
</description>
<tutorials>
<link title="Importing translations">$DOCS_URL/tutorials/assets_pipeline/importing_translations.html</link>
</tutorials>
<members>
<member name="compress" type="bool" setter="" getter="" default="true">
If [code]true[/code], creates an [OptimizedTranslation] instead of a [Translation]. This makes the resulting file smaller at the cost of a small CPU overhead.
<member name="compress" type="int" setter="" getter="" default="1">
- [b]Disabled[/b]: Creates a [Translation].
- [b]Auto[/b]: Creates an [OptimizedTranslation] when possible. This makes the resulting file smaller at the cost of a small CPU overhead. Falls back to [Translation] for translations with context or plural forms.
</member>
<member name="delimiter" type="int" setter="" getter="" default="0">
The delimiter to use in the CSV file. The default value matches the common CSV convention. Tab-separated values are sometimes called TSV files.
</member>
<member name="unescape_keys" type="bool" setter="" getter="" default="false">
If [code]true[/code], message keys in the CSV file are unescaped using [method String.c_unescape] during the import process.
</member>
<member name="unescape_translations" type="bool" setter="" getter="" default="true">
If [code]true[/code], message translations in the CSV file are unescaped using [method String.c_unescape] during the import process.
</member>
</members>
</class>