Skip to content

Commit

Permalink
Merge branch 'translations' into fabric
Browse files Browse the repository at this point in the history
  • Loading branch information
Earthcomputer committed Nov 26, 2024
2 parents 755641d + 510982e commit 322761d
Show file tree
Hide file tree
Showing 19 changed files with 1,145 additions and 112 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ Patreon: https://www.patreon.com/earthcomputer
and move it to the mods folder (`.minecraft/mods`).

## Contributing
See the [contribution guidelines](docs/CONTRIBUTING.md)
To contribute translations, see the [translation contribution guidelines](docs/TRANSLATING.md).

For other contributions, see the [contribution guidelines](docs/CONTRIBUTING.md).
114 changes: 114 additions & 0 deletions docs/TRANSLATING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Translating
Anybody can contribute translations to clientcommands via its
[Transifex page](https://app.transifex.com/earthcomputer/clientcommands).

![transifex.png](translating/transifex.png)

## Getting started

1. Go to the [clientcommands Transifex page](https://app.transifex.com/earthcomputer/clientcommands).
2. Click "join this project" to create an open source account so that you can contribute to clientcommands.
Do **not** click "sign up" as this will create the wrong type of account.

![join_project.png](translating/join_project.png)

3. You can either sign up via GitHub or via email. If signing up via email, just put in your regular email, don't worry
about it being a "business" email.

![sign_up.png](translating/sign_up.png)

4. Finish setting up your account by selecting which languages you know and whatever else it asks you.
5. Now, when visiting the clientcommands Transifex page, you are ready to add or make changes to translations.
Click on the "editor" button on the sidebar and then select which language you would like to translate into with the
dropdown on the top panel.

![editor_button.png](translating/editor_button.png)

![select_language.png](translating/select_language.png)

## How to translate
### General guidelines
Translation is an art, not a science, and sometimes there is not a word-for-word translation that feels natural in the
target language. Your goal is to translate the *meaning* of the phrase, not the *words*. Sometimes significant
rephrasing is required to preserve the same meaning of a sentence in the target language, and that's okay.

### String substitutions
A string substitution is a placeholder that will be replaced by a number or another string when the user sees it. In the
English, substitutions will always look like `%s`, which looks like this in the Transifex editor:

![percent_s.png](translating/percent_s.png)

I don't know why there is a "1" in there, you can ignore that. For example, the `/cfinditem` success translation reads
`Found %s at %s, %s blocks away`, which might show up to the user as
`Found minecraft:stone at (45, 87, 24) [Glow], 25.47 blocks away`. If the substitutions in your translation appear in
the same order as in the English, you can use `%s`. If you want substitutions to appear in a different order than in the
English, then you need to use `%1$s`, `%2$s`, `%3$s` etc, where the numbers are referring to which substitution it is.
For example, the simplified Chinese translation for `/cfinditem` success is `在%2$s找到%1$s, 距离你%3$s格`, which might
show up to the user as `在(45, 87, 24) [发光]找到minecraft:stone, 距离你25.47格` (notice how the coordinates and the item
type are the other way round from in English).

### Minecraft terminology

Try to look for examples of Minecraft-specific terminology (such as "item", "entity", "creeper" etc) in the
[official Minecraft translations](https://crowdin.com/project/minecraft) (requires an account to view, or you can try
to find them in-game). If it exists then use that. For example, in German, "item" is consistently translated as
"Gegenstand" in Minecraft, so always use "Gegenstand" in German to be consistent with the rest of Minecraft.

### Computer terminology

If you're looking for technical terminology that's not specific to Minecraft but is related to computers, or
programming, you can look at
[Microsoft Terminology](https://learn.microsoft.com/en-us/globalization/reference/microsoft-terminology) to see if there
is any precedent for translating this term in any of Microsoft's programs.

### Figuring out context

Often the way you translate a phrase depends on the context in which that phrase is used. Here are some ways you can
find out the context of a translation:

#### String instructions
Some particularly difficult translations have instructions on how to translate them, which are found under the English:

![string_instructions.png](translating/string_instructions.png)

#### Translation key
Often the clue you need is found in the translation key, which is how the translation is referenced in the code. In the
example below, the translation key for `Alias "%s" not found` is `commands.calias.notFound`, which indicates that this
message may appear after running the `/calias` command. Once you know what the `/calias` command does, you know what
sense of the word "alias" you're translating which should make things easier (if you're still stuck, the Microsoft
Terminology Search linked above will help with this example).

![translation_key.png](translating/translation_key.png)

#### Read the code
If you're able to read Java code, you can find where the translation key is used in the clientcommands codebase to
figure out the context. Don't worry if you're not able to do this.

#### Ask in Discord
If you're still stuck on what the context is, you can ask in the `clientcommands-dev` channel on
[Discord](https://discord.gg/Jg7Bun7). We'll explain the context needed to translate the string. We may also add a
string instruction to help others with this translation in the future.

### Plurals
In languages with plurals, when there is an unknown number of a particular noun, always use the most general form of the
noun that will apply to most circumstances. Do not attempt to account for other forms of the noun such as the singular,
dual, etc.

For example, it should be `%s blocks away` rather than `%s block(s) away`, and `%s Blöcke entfernt` in German rather
than `%s Block/Blöcke entfernt`, even though the user may end up seeing `1 blocks away`.

I understand that this differs from the official Minecraft translations, at least for English. However, for languages
with more complicated plurals this can end up creating a mess which is harder to read than if the grammar can be
sometimes incorrect but still understandable. This is the compromise I have decided to go for until Mojang adds a better
way to handle plurals.

## Requesting new languages
If your language isn't in the list of target languages for clientcommands, you can request for it to be added via
[Discord](https://discord.gg/Jg7Bun7) or via [GitHub issues](https://github.com/Earthcomputer/clientcommands/issues/).
A language is eligible to be added if it is supported by both Minecraft and Transifex. All eligible requests will be
accepted.

## Becoming a reviewer
You can ask in Discord to become a reviewer, which allows you to verify translations as correct and appropriate. You
should be able to become a reviewer if you're a trusted member of the community or you have a history of providing good
translations.
Binary file added docs/translating/editor_button.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/translating/join_project.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/translating/percent_s.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/translating/select_language.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/translating/sign_up.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/translating/string_instructions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/translating/transifex.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/translating/translation_key.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 37 additions & 1 deletion src/main/resources/assets/clientcommands/lang/de_de.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"commands.calias.addAlias.success": "Alias \"%s\" erfolgreich hinzugefügt",
"commands.calias.listAliases.noAliasesRegistered": "Keine Aliasse registriert",
"commands.calias.listAliases.success": "%s registrierte Aliasse:",
"commands.calias.recursive": "Recursive alias \"%s\"",
"commands.calias.removeAlias.success": "Alias \"%s\" erfolgreich entfernt",

"commands.careastats.notLoaded": "Ein Chunk in diesem Bereich ist nicht geladen",
Expand Down Expand Up @@ -73,6 +74,7 @@
"commands.cfindblock.starting": "Suche nach %s",
"commands.cfindblock.success": "Nächster passender Block ist an %s, %s Blöcke entfernt",

"commands.cfinditem.match.entity": "%sx %s found in %s at %s",
"commands.cfinditem.match": "%sx %s wurden an %s gefunden",
"commands.cfinditem.starting": "Suche nach %s",
"commands.cfinditem.starting.keepSearching": "Suche unendlich lange nach %s.",
Expand Down Expand Up @@ -152,6 +154,8 @@
"commands.clisten.list": "Warte auf die folgenden Pakete:",
"commands.clisten.clear": "Warte auf kein Paket mehr",

"commands.cminesweeper.tooManyMines": "Too many mines, must be between 0 and 9 less than than the amount of total tiles",

"commands.cplayerinfo.ioException": "Ein Fehler ist aufgetreten",
"commands.cplayerinfo.getNameHistory.success": "%s hatte die folgenden Namen: %s",

Expand Down Expand Up @@ -180,6 +184,14 @@

"commands.csignsearch.starting": "Suche Schilder",

"commands.csnap.airborne": "You cannot snap while airborne",
"commands.csnap.cannotFit": "The player cannot fit at that location",
"commands.csnap.clickToTeleportEnabled": "Enabled click to teleport",
"commands.csnap.clickToTeleportDisabled": "Disabled click to teleport",
"commands.csnap.success": "Snapped to %s %s %s",
"commands.csnap.tooFar": "You can only snap to locations at most 1 block away",
"commands.csnap.wall": "You cannot snap onto walls",

"commands.cstartup.add.success": "Befehl zu Start-Datei hinzugefügt",
"commands.cstartup.couldNotCreateFile": "Konnte Start-Datei nicht erstellen",
"commands.cstartup.couldNotEdit": "Konnte Start-Datei nicht bearbeiten",
Expand All @@ -189,11 +201,15 @@
"commands.cstopsound.success.source.any": "Alle Geräusche von '%s' wurden für dich selbst gestoppt",
"commands.cstopsound.success.source.sound": "Gräusch '%s' von der Quelle '%s' wurde für dich selbst gestoppt",

"commands.ctask.conflicting": "A conflicting task '%s' is already running. %s",
"commands.ctask.list.noTasks": "Derzeit werden keine Aufgaben ausgeführt",
"commands.ctask.list.success": "Derzeit werden %s Aufgaben ausgeführt",
"commands.ctask.stop.noMatch": "Keine passenden Aufgaben",
"commands.ctask.stop.success": "%s Aufgaben wurden beendet",

"commands.ctictactoe.playerNotFound": "Spieler nicht gefunden",
"commands.ctictactoe.noGameWithPlayer": "Currently not playing a game with that player",

"commands.ctime.reset.success": "Die Zeit ist jetzt mit dem Server synchronisiert",

"commands.ctitle.cleared": "Titel gelöscht",
Expand Down Expand Up @@ -245,6 +261,7 @@
"commands.client.invalidHoverAction": "Ungültige Hoverereignisaktion '%s'",
"commands.client.invalidHoverEvent": "Ungültiges Hoverereignis '%s'",
"commands.client.notClient": "Kein Klientenbefehl",
"commands.client.regexTooSlow": "Regex '%s' was too slow to match",
"commands.client.requiresRestart": "Diese Änderung wird erst nach einem Neustart verfügbar",
"commands.client.tooFewArguments": "Zu wenige Argumente",

Expand Down Expand Up @@ -279,6 +296,10 @@

"itemCrack.notEnoughItems": "Kann RNG-SeedCracker nicht benutzen: Nicht genug Gegenstände in der Hand des Spielers",

"minesweeperGame.minesLeft": "Mines Left: %s",
"minesweeperGame.timePlayed": "Time Played: %ss",
"minesweeperGame.title": "Minesweeper",

"playerManip.state": "Spielerknackzustand: %s",
"playerManip.state.uncracked": "Ungeknackt",
"playerManip.state.cracked": "Geknackt",
Expand All @@ -304,6 +325,7 @@
"playerManip.reset.anvil": "Amboss benutzt",
"playerManip.reset.food": "Gegessen",
"playerManip.reset.drink": "Getrunken",
"playerManip.reset.consume": "Consumed",
"playerManip.reset.baneOfArthropods": "Gliederfüßer mit Nemesis der Gliederfüßer geschlagen",
"playerManip.reset.advancement": "Fortschritt erzielt",
"playerManip.reset.shield": "Mit Schild abgewehrt",
Expand All @@ -325,6 +347,11 @@
"snakeGame.title": "Snake",
"snakeGame.score": "Punkte: %s",

"ticTacToeGame.title": "Tic-tac-toe against %s",
"ticTacToeGame.playingWith": "You are playing with %s",
"ticTacToeGame.noughts": "noughts (O)",
"ticTacToeGame.crosses": "crosses (X)",

"c2cpacket.messageTooLong": "Nachricht zu lange (max. 255 Zeichen) %s Zeichen gefunden",
"c2cpacket.publicKeyNotFound": "Öffentlicher Schlüssel nicht gefunden",
"c2cpacket.encryptionFailed": "Beim Verschlüsseln deiner Nachricht ist etwas schief gegangen",
Expand All @@ -333,5 +360,14 @@
"c2cpacket.sentC2CPacket": "Du hast ein C2C-Paket gesendet, aber du akzeptierst keine eingehenden C2C-Pakete!",

"c2cpacket.messageC2CPacket.incoming": "%s -> du: %s",
"c2cpacket.messageC2CPacket.outgoing": "du -> %s: %s"
"c2cpacket.messageC2CPacket.outgoing": "du -> %s: %s",

"c2cpacket.startTicTacToeGameC2CPacket.outgoing.invited": "You invited %s to a game of tic-tac-toe",
"c2cpacket.startTicTacToeGameC2CPacket.incoming": "%s invited you to a game of tic-tac-toe",
"c2cpacket.startTicTacToeGameC2CPacket.incoming.accept": "Accept",
"c2cpacket.startTicTacToeGameC2CPacket.incoming.accept.hover": "Click to accept",
"c2cpacket.startTicTacToeGameC2CPacket.incoming.accepted": "%s has accepted your invitation, click to make your move",
"c2cpacket.startTicTacToeGameC2CPacket.outgoing.accept": "Accepted the invitation, your opponent will go first",
"c2cpacket.putTicTacToeMarkC2CPacket.incoming.lost": "%s has made a move in tic-tac-toe and won",
"c2cpacket.putTicTacToeMarkC2CPacket.incoming": "%s has made a move in tic-tac-toe, click to make your move"
}
53 changes: 52 additions & 1 deletion src/main/resources/assets/clientcommands/lang/id_id.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"commands.calias.addAlias.success": "Berhasil menambahkan alias \"%s\"",
"commands.calias.listAliases.noAliasesRegistered": "Tidak ada alias yang didaftar",
"commands.calias.listAliases.success": "Ada %s alias yang didaftar:",
"commands.calias.recursive": "Recursive alias \"%s\"",
"commands.calias.removeAlias.success": "Berhasil menghapus alias \"%s\"",

"commands.careastats.notLoaded": "Bingkah di area tersebut tidak termuat",
Expand Down Expand Up @@ -73,6 +74,7 @@
"commands.cfindblock.starting": "Mencari %s",
"commands.cfindblock.success": "Hasil paling dekat adalah di %s, %s block",

"commands.cfinditem.match.entity": "%sx %s found in %s at %s",
"commands.cfinditem.match": "%sx %s ketemu di %s",
"commands.cfinditem.starting": "Mencari benda %s",
"commands.cfinditem.starting.keepSearching": "Mencari benda %s selamanya.",
Expand Down Expand Up @@ -137,6 +139,23 @@
"commands.ckit.list": "Kit yang tersedia: %s",
"commands.ckit.list.empty": "Tidak ada kit yang tersedia",

"commands.clisten.commandDisabled": "The command was disabled, check your logs",
"commands.clisten.unknownPacket": "Unknown packet %s",
"commands.clisten.sentPacket": "Sent the following packet: %s",
"commands.clisten.receivedPacket": "Received the following packet: %s",
"commands.clisten.sentC2CPacket": "Sent the following C2C packet: %s",
"commands.clisten.receivedC2CPacket": "Received the following C2C packet: %s",
"commands.clisten.packetError": "ERROR",
"commands.clisten.add.success": "Successfully started listening to that packet",
"commands.clisten.add.failed": "Already listening to that packet",
"commands.clisten.remove.success": "No longer listening to that packet",
"commands.clisten.remove.failed": "Not listening to that packet",
"commands.clisten.list.none": "Not listening to any packets",
"commands.clisten.list": "Listening to the following packets:",
"commands.clisten.clear": "No longer listening to any packets",

"commands.cminesweeper.tooManyMines": "Too many mines, must be between 0 and 9 less than than the amount of total tiles",

"commands.cplayerinfo.ioException": "Terjadi sebuah kesalahan",
"commands.cplayerinfo.getNameHistory.success": "%s memiliki nama nama berikut: %s",

Expand Down Expand Up @@ -165,6 +184,14 @@

"commands.csignsearch.starting": "Pencari petanda",

"commands.csnap.airborne": "You cannot snap while airborne",
"commands.csnap.cannotFit": "The player cannot fit at that location",
"commands.csnap.clickToTeleportEnabled": "Enabled click to teleport",
"commands.csnap.clickToTeleportDisabled": "Disabled click to teleport",
"commands.csnap.success": "Snapped to %s %s %s",
"commands.csnap.tooFar": "You can only snap to locations at most 1 block away",
"commands.csnap.wall": "You cannot snap onto walls",

"commands.cstartup.add.success": "Perintah ditambahkan ke file startup",
"commands.cstartup.couldNotCreateFile": "Tidak bisa membuat file startup",
"commands.cstartup.couldNotEdit": "Tidak bisa mengubah file startup",
Expand All @@ -174,11 +201,15 @@
"commands.cstopsound.success.source.any": "Memberhentikan semua suara '%s' dari diri sendiri",
"commands.cstopsound.success.source.sound": "Memberhentikan suara '%s' di kategori '%s' dari diri sendiri",

"commands.ctask.conflicting": "A conflicting task '%s' is already running. %s",
"commands.ctask.list.noTasks": "Tidak ada tugas yang berjalan",
"commands.ctask.list.success": "%s sedang menjalankan tugas",
"commands.ctask.stop.noMatch": "Tidak ada tugas yang cocok",
"commands.ctask.stop.success": "Memberhentikan tugas %s",

"commands.ctictactoe.playerNotFound": "Pemain tidak ditemukan",
"commands.ctictactoe.noGameWithPlayer": "Currently not playing a game with that player",

"commands.ctime.reset.success": "Waktunya sekarang cocok dengan server",

"commands.ctitle.cleared": "Judul dihapus",
Expand Down Expand Up @@ -230,6 +261,7 @@
"commands.client.invalidHoverAction": "Aksi sorot tidak valid '%s'",
"commands.client.invalidHoverEvent": "Peristiwa sorot tidak valid '%s'",
"commands.client.notClient": "Bukan perintah sisi klien",
"commands.client.regexTooSlow": "Regex '%s' was too slow to match",
"commands.client.requiresRestart": "Perubahan ini akan berlaku setelah Anda memulai ulang game Anda",
"commands.client.tooFewArguments": "Argumen terlalu sedikit",

Expand Down Expand Up @@ -264,6 +296,10 @@

"itemCrack.notEnoughItems": "Tidak bisa menggunakkan SeedCracker RNG: Tidak cukup benda di Tangan Pemain",

"minesweeperGame.minesLeft": "Mines Left: %s",
"minesweeperGame.timePlayed": "Time Played: %ss",
"minesweeperGame.title": "Minesweeper",

"playerManip.state": "Status Memecahkan Pemain: %s",
"playerManip.state.uncracked": "Belum pecah",
"playerManip.state.cracked": "Sudah pecah",
Expand All @@ -289,6 +325,7 @@
"playerManip.reset.anvil": "Menggunakkan Paron",
"playerManip.reset.food": "Makan",
"playerManip.reset.drink": "Minum",
"playerManip.reset.consume": "Consumed",
"playerManip.reset.baneOfArthropods": "Pemain menyakiti serangga menggunakkan pesona Kutukan Artropoda",
"playerManip.reset.advancement": "Mendapatkan Advancement",
"playerManip.reset.shield": "Blok menggunakkan Perisai",
Expand All @@ -310,6 +347,11 @@
"snakeGame.title": "Game Ular",
"snakeGame.score": "Skor: %s",

"ticTacToeGame.title": "Tic-tac-toe against %s",
"ticTacToeGame.playingWith": "You are playing with %s",
"ticTacToeGame.noughts": "noughts (O)",
"ticTacToeGame.crosses": "crosses (X)",

"c2cpacket.messageTooLong": "Pesan terlalu panjang (max. 255 karakter) saat ini %s karakter",
"c2cpacket.publicKeyNotFound": "Kunci publik tidak ditemukan",
"c2cpacket.encryptionFailed": "Terjadi kegagalan saat mengenkripsi pesan Anda ",
Expand All @@ -318,5 +360,14 @@
"c2cpacket.sentC2CPacket": "Anda telah mengirimkan paket C2C, tetapi Anda tidak menerima paket C2C yang masuk!",

"c2cpacket.messageC2CPacket.incoming": "%s -> Anda: %s",
"c2cpacket.messageC2CPacket.outgoing": "Anda -> %s: %s"
"c2cpacket.messageC2CPacket.outgoing": "Anda -> %s: %s",

"c2cpacket.startTicTacToeGameC2CPacket.outgoing.invited": "You invited %s to a game of tic-tac-toe",
"c2cpacket.startTicTacToeGameC2CPacket.incoming": "%s invited you to a game of tic-tac-toe",
"c2cpacket.startTicTacToeGameC2CPacket.incoming.accept": "Accept",
"c2cpacket.startTicTacToeGameC2CPacket.incoming.accept.hover": "Click to accept",
"c2cpacket.startTicTacToeGameC2CPacket.incoming.accepted": "%s has accepted your invitation, click to make your move",
"c2cpacket.startTicTacToeGameC2CPacket.outgoing.accept": "Accepted the invitation, your opponent will go first",
"c2cpacket.putTicTacToeMarkC2CPacket.incoming.lost": "%s has made a move in tic-tac-toe and won",
"c2cpacket.putTicTacToeMarkC2CPacket.incoming": "%s has made a move in tic-tac-toe, click to make your move"
}
Loading

0 comments on commit 322761d

Please sign in to comment.