Autogenerate .tr files from .po files
This commit is contained in:
parent
bed66e0f90
commit
425b0993d3
|
@ -6,6 +6,7 @@ packages:
|
|||
- unzip
|
||||
- wget
|
||||
- lua-busted
|
||||
- luajit
|
||||
sources :
|
||||
- https://git.sr.ht/~gpcf/advtrains
|
||||
|
||||
|
@ -40,3 +41,8 @@ tasks:
|
|||
- run_test_world: |
|
||||
echo "bind_address = 127.0.0.1" > minetest.conf
|
||||
minetestserver --port 31111 --gameid minetest_game --config ~/minetest.conf --world ~/.minetest/worlds/advtrains_testworld --logfile ~/minetest.log
|
||||
- test_po_files : |
|
||||
cd advtrains/advtrains
|
||||
for f in po/*.po; do
|
||||
luajit -e 'require("poconvert").from_string("advtrains", io.input():read("*a"))' < $f
|
||||
done
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
## Eclipse project files & directories
|
||||
.project
|
||||
.settings
|
||||
*~
|
||||
advtrains/locale/*.tr
|
||||
advtrains/po/*~
|
||||
|
|
|
@ -22,8 +22,6 @@ Copyright (C) 2016-2020 Moritz Blei (orwell96) and contributors
|
|||
local lot = os.clock()
|
||||
minetest.log("action", "[advtrains] Loading...")
|
||||
|
||||
attrans = minetest.get_translator("advtrains")
|
||||
|
||||
--advtrains
|
||||
advtrains = {trains={}, player_to_train_mapping={}}
|
||||
|
||||
|
@ -200,6 +198,10 @@ advtrains.meseconrules =
|
|||
|
||||
advtrains.fpath=minetest.get_worldpath().."/advtrains"
|
||||
|
||||
advtrains.poconvert = dofile(advtrains.modpath.."/poconvert.lua")
|
||||
advtrains.poconvert.from_flat("advtrains")
|
||||
attrans = minetest.get_translator("advtrains")
|
||||
|
||||
advtrains.speed = dofile(advtrains.modpath.."/speed.lua")
|
||||
advtrains.texture = dofile(advtrains.modpath.."/texture.lua")
|
||||
|
||||
|
@ -233,7 +235,6 @@ end
|
|||
|
||||
dofile(advtrains.modpath.."/lzb.lua")
|
||||
|
||||
|
||||
--load/save
|
||||
|
||||
-- backup variables, used if someone should accidentally delete a sub-mod
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
# Translations
|
||||
**Please note that this document is outdated as transition to `.po`
|
||||
files is currently in progress.**
|
||||
|
||||
Please read this document before working on any translations.
|
||||
|
||||
## Getting Started
|
||||
If there is a translation file for your language (e.g. German), you can
|
||||
edit the file directly. Please read [the documentation on the
|
||||
translation file format][tr-format].
|
||||
|
||||
Alternatively, Advtrains provides a script named `gui` that can be used
|
||||
to, among other things, edit translation files. The script requires
|
||||
Tcl/Tk 8.6, which is provided by most Linux distributions.
|
||||
|
||||
If the translation file for your language does not exist, create it by
|
||||
copying `template.txt` to `advtrains.XX.tr`, where `XX` is replaced by
|
||||
the language code.
|
||||
|
||||
Feel free to use the [discussion mailing list][srht-discuss] if you
|
||||
have any questions regarding localization.
|
||||
|
||||
You can share your `.tr` file directly or [as a patch][gsm] to the [dev
|
||||
mailing list][srht-devel]. The latter is encouraged, but, unlike code
|
||||
changes, translation files sent directly are also accepted.
|
||||
|
||||
[tr-format]: https://minetest.gitlab.io/minetest/translations/#translation-file-format
|
||||
[srht-discuss]: https://lists.sr.ht/~gpcf/advtrains-discuss
|
||||
[srht-devel]: https://lists.sr.ht/~gpcf/advtrains-devel
|
||||
[gsm]: https://git-send-email.io
|
||||
|
||||
## Translation Notes
|
||||
* Translations should be consistent. You can use other entries or the
|
||||
translations in Minetest as a reference.
|
||||
* Translations do not have to fully correspond to the original text -
|
||||
they only need to provide the same information. In particular,
|
||||
translations do not need to have the same linguistical structure as the
|
||||
original text.
|
||||
* Replacement sequences (`@1`, `@2`, etc) should not be translated.
|
||||
* Certain abbreviations or names, such as "Ks" or "Zs 3", should
|
||||
generally not be translated.
|
||||
|
||||
### (de) German
|
||||
* Verwenden Sie die neue Rechtschreibung und die Sie-Form.
|
||||
* Mit der deutschen Tastaturbelegung unter Linux können die
|
||||
Anführungszeichen „“ mit AltGr-V bzw. AltGr-B eingegeben werden.
|
||||
|
||||
### (zh) Chinese
|
||||
(This section is written in English to avoid writing the note twice or
|
||||
using only one of the variants, as most of this section applies to both
|
||||
the traditional and simplified variants.)
|
||||
|
||||
* Please use the 「」 quotation marks for Traditional Chinese and “”
|
||||
for Simplified Chinese.
|
||||
* Please use the fullwidth variants of: , 、 。 ? ! : ;
|
||||
* Please use the halfwidth variants of: ( ) [ ] / \ |
|
||||
* Please do not leave any space between Han characters (including
|
||||
fullwidth punctuation marks).
|
||||
* Please leave a space between Han characters (excluding fullwidth
|
||||
punctuation marks) and characters from other scripts (including
|
||||
halfwidth punctuation marks). However, do not leave any space between
|
||||
Han characters and Arabic numerals.
|
||||
|
||||
## Notes for developers
|
||||
* Avoid word-by-word translations.
|
||||
* Avoid manipulating translated strings (except for concatenation). Use
|
||||
server-side translations if you have to modify the text sent to users.
|
||||
* Avoid truncating strings unless multibyte characters are handled
|
||||
properly.
|
|
@ -0,0 +1 @@
|
|||
../po/README.md
|
|
@ -1,159 +0,0 @@
|
|||
# textdomain: advtrains
|
||||
|
||||
# Advtrains Core (unorganized)
|
||||
This wagon is owned by @1, you can't destroy it.=Dieser Waggon gehört @1, Sie dürfen ihn nicht abbauen.
|
||||
Warning: If you destroy this wagon, you only get some steel back! If you are sure, hold Sneak and left-click the wagon.=Warnung: Durch den Abbau des Waggons erhalten Sie nur etwas Stahl zurück. Nutzen Sie Schleichen+Linksklick, um dem Waggon abzubauen.
|
||||
This position is protected!=Diese Position ist geschützt!
|
||||
Can't place: not pointing at node=Es kann nicht platziert werden: Sie zeigen nicht auf einem Block.
|
||||
Can't place: space occupied!=Es kann nicht platziert werden: diese Position ist besetzt.
|
||||
Can't place: protected position!=Es kann nicht platziert werden: diese Position ist geschützt.
|
||||
Can't place: Not enough slope items left (@1 required)=Es kann nicht platziert werden: Sie haben nicht genug Steigungsblöcke, es werden insgesamt @1 benötigt.
|
||||
Can't place: There's no slope of length @1=Es kann nicht platziert werden: die Steigung der Länge @1 ist nicht definiert.
|
||||
Can't place: no supporting node at upper end.=Es kann nicht platziert werden: es gibt keinen unterstützenden Block am Ende der Steigung.
|
||||
Deprecated Track=ausrangiertes Gleis, nicht verwenden.
|
||||
Can't get on: wagon full or doors closed!=Sie können nicht einsteigen: der Waggon ist voll oder die Türen sind geschlossen.
|
||||
Use Sneak+rightclick to bypass closed doors!=Nutzen Sie Schleichen+Rechtsklick, um trotz geschlossener Türen einzusteigen.
|
||||
Doors are closed! Use Sneak+rightclick to ignore the closed doors and get off!=Die Türen sind geschlossen. Nutzen Sie Schleichen+Rechtsklick, um trotz geschlossener Türen auszusteigen.
|
||||
Access to @1=Zugang zu @1
|
||||
You do not have the @1 privilege.=Ihnen fehlt das „@1“-Privileg.
|
||||
The wagon's inventory is not empty!=Das Inventar dieses Waggons ist nicht leer!
|
||||
Position is occupied by a train.=Ein Zug steht an dieser Position.
|
||||
There's a Track Circuit Break here.=Hier ist eine Gleisabschnittsgrenze (TCB).
|
||||
There's a Signal Influence Point here.=Hier ist ein Signal-Beeinflussungspunkt.
|
||||
|
||||
# Trackworker, rotation, adjustment
|
||||
This node can't be rotated using the trackworker!=Dieser Block kann nicht mit dem Gleiswerkzeug gedreht werden.
|
||||
This node can't be changed using the trackworker!=Dieser Block kann nicht mit dem Gleiswerkzeug bearbeitet werden.
|
||||
This track can not be changed!=Dieses Gleis kann nicht geändert werden!
|
||||
This track can not be rotated!=Dieses Gleis kann nicht gedreht werden!
|
||||
This track can not be removed!=Dieses Gleis kann nicht entfernt werden!
|
||||
|
||||
# ATC
|
||||
ATC controller, unconfigured.=Nicht konfiguierte Zugbeeinflussungsgleis
|
||||
ATC controller=Zugbeeinflussungsgleis
|
||||
ATC controller, mode @1@nChannel: @2=Zugbeeinflussungsgleis in Betriebsart „@1“@nKanal: @2
|
||||
ATC controller, mode @1@nCommand: @2=Zugbeeinflussungsgleis in Betriebsart „@1“@nBefehl: @2
|
||||
Command=Befehl
|
||||
Command (on)=Befehl (wenn aktiviert)
|
||||
Digiline channel=Digiline-Kanal
|
||||
ATC Kick command warning: Doors closed=ATC Kick command warning: Doors closed
|
||||
ATC Kick command warning: Train moving=ATC Kick command warning: Train moving
|
||||
ATC Reverse command warning: didn't reverse train, train moving!=Zugbeeinflussung: der Befehl „R“ wurde nicht ausgeführt, Zug in Bewegung!
|
||||
ATC command syntax error: I statement not closed: @1=Zugbeeinflussung: Unvollständiger I-Befehl: @1
|
||||
ATC command parse error: Unknown command: @1=Zugbeeinflussung: Unbekannter Befehl: @1
|
||||
|
||||
# Coupling
|
||||
Lock couples=Kupplungen sperren
|
||||
You need to own at least one neighboring wagon to destroy this couple.=Sie müssen Besitzer eines angrenzenden Waggons sein, um hier abzukuppeln.
|
||||
Buffer and Chain Coupler=Schraubenkupplung
|
||||
Scharfenberg Coupler=Scharfenbergkupplung
|
||||
Japanese Train Inter-Wagon Connection=Waggonzwischenverbindung Japanischer Personenzüge
|
||||
Can not couple: The couplers of the trains do not match (@1 and @2).=Die Kupplungen der Züge passen nicht zueinander (@1 und @2).
|
||||
You are not allowed to couple trains without the train_operator privilege.=Sie dürfen ohne das „train_builder“-Privileg keine Züge ankuppeln.
|
||||
|
||||
# Clipboard
|
||||
The track you are trying to place the wagon on is not long enough!=Das Gleis, auf dem der Waggon platziert werden woll, ist zu kurz.
|
||||
The clipboard couldn't access the metadata. Paste failed.=Wegen des fehlgeschlagenen Zugriffs auf die Metadaten konnte eine Kopie des Zuges nicht eingefügt werden.
|
||||
The clipboard couldn't access the metadata. Copy failed.=Wegen des fehlgeschlagenen Zugriffs auf die Metadaten konnte der Zug nicht kopiert werden.
|
||||
The clipboard is empty.=Das Clipboard ist leer.
|
||||
Back of train would end up off track, cancelling.=Der hinterer Teil dez Zuges wäre nicht auf dem Gleis.
|
||||
No such lua entity!=Sie zeigen nicht auf einem Objekt, das mit diesem Werkzeug kopiert werden kann.
|
||||
No such wagon: @1=Es gibt keinen mit „@1“ identifizierbaren Waggon.
|
||||
No such train: @1=Es gibt keinen mit „@1“ identifizierbaren Zug.
|
||||
Train copied!=Der Zug wurde Kopiert.
|
||||
|
||||
# Protection
|
||||
You are not allowed to build tracks without the track_builder privilege.=Sie dürfen ohne das „track_builder“-Privileg kein Gleis bauen.
|
||||
You are not allowed to build near tracks without the track_builder privilege.=Sie dürfen ohne das „track_builder“-Privileg nicht in der Nähe von Gleisen bauen.
|
||||
You are not allowed to build tracks at this protected position.=Sie dürfen an geschützten Stellen kein Gleis bauen.
|
||||
You are not allowed to build near tracks at this protected position.=Sie dürfen an geschützten Stellen nicht in der Nähe von Gleisen bauen.
|
||||
You are not allowed to operate turnouts and signals without the railway_operator privilege.=Sie dürfen ohne das „railway_operator“-Privileg keine Bahnanlage operieren.
|
||||
|
||||
# Train HUD/Formspecs
|
||||
Speed:=Geschw.:
|
||||
Target:=Zielges.:
|
||||
Show Inventory=Inventar Zeigen
|
||||
Select seat:=Wählen Sie einen Sitzplatz aus:
|
||||
Wagon properties=Waggon-Einstellungen
|
||||
Save wagon properties=Waggon-Einstellungen speichern
|
||||
Text displayed outside on train=Äußere Anzeige
|
||||
Text displayed inside train=Innere Anzeige
|
||||
Line=Linie
|
||||
Routingcode=Routingcode
|
||||
Get off=Aussteigen
|
||||
Get off (forced)=Ausstieg zwingen
|
||||
(Doors closed)=(Türen geschlossen)
|
||||
|
||||
# General
|
||||
Save=Speichern
|
||||
|
||||
# Line automation
|
||||
Station Code=Code der Haltestelle
|
||||
Station Name=Name der Haltestelle
|
||||
Door Delay=Zeit für die Türschließung
|
||||
Door Side=Door Side
|
||||
Dep. Speed=Zielgeschwindigkeit bei Abfahrt
|
||||
Stop Time=Wartezeit
|
||||
|
||||
# Items
|
||||
Track Worker Tool@n@nLeft-click: change rail type (straight/curve/switch)@nRight-click: rotate rail/bumper/signal/etc.=Gleiswerkzeug@n@nLinksklick: Gleistyp ändern, Rechtsklick: Objekt drehen.
|
||||
Passive Component Naming Tool@n@nRight-click to name a passive component.=PC-Benennungswerkzeug@n@nRechtsklick zur Benennung der passiven Komponente
|
||||
Train copy/paste tool@n@nLeft-click: copy train@nRight-click: paste train=Werkzeug zur Erstellung von Zugkopien@n@nLinksklick: Zug ins Clipboard kopieren@nRight-click: Kopierten Zug einfügen
|
||||
Track=Gleis
|
||||
Perpendicular Diamond Crossing Track=Kreuzung mit zueinander orthogonalen Gleisen
|
||||
Diagonal Diamond Crossing Track=Diagonale Gleiskreuzung
|
||||
90+Angle Diamond Crossing Track=Kreuzung mit einem achsenparallelen Gleis
|
||||
Y-turnout=Y-Weiche
|
||||
3-way turnout=Dreiwegweiche
|
||||
Unloading Track=Abladungsgleis
|
||||
Loading Track=Beladungsgleis
|
||||
Bumper=Prellbock
|
||||
Detector Rail=Detektorgleis
|
||||
@1 Slope=@1 Steigung
|
||||
@1 Platform (low)=Niedriger @1-Bahnsteig
|
||||
@1 Platform (high)=Hoher @1-Bahnsteig
|
||||
@1 Platform (low, 45 degree)=Niedriger @1-Bahnsteig (45°)
|
||||
@1 Platform (45 degree)=Hoher @1-Bahnsteig (45°)
|
||||
Lampless Signal=Mechanisches Signal
|
||||
Signal=Lichtsignal
|
||||
Wallmounted Signal (l)=An der linken Seite montiertes Signal
|
||||
Wallmounted Signal (r)=An der rechten Seite montiertes Signal
|
||||
Wallmounted Signal (t)=An der Decke montiertes Signal
|
||||
Andrew's Cross=Andrew's Cross
|
||||
Boiler=Boiler
|
||||
driver's cab=driver's cab
|
||||
Wheel=Wheel
|
||||
Chimney=Chimney
|
||||
|
||||
# Seats
|
||||
Default Seat=Standardsitzplatz
|
||||
Default Seat (driver stand)=Standardsitzplatz (Führerstand)
|
||||
Driver stand=Führerstand
|
||||
Driver Stand (left)=Führerstand Links
|
||||
Driver Stand (right)=Führerstand Rechts
|
||||
|
||||
# Wagon/engine types
|
||||
Industrial Train Engine=Industrielle Lokomotive
|
||||
Big Industrial Train Engine=Große Industrielle Lokomotive
|
||||
Industrial tank wagon=Tankwaggon
|
||||
Industrial wood wagon=Holztransportwaggon
|
||||
Japanese Train Engine=Japanische Personenzug-Lokomotive
|
||||
Japanese Train Wagon=Japanischer Personenzug-Passagierwaggon
|
||||
Steam Engine=Dampflokomotive
|
||||
Detailed Steam Engine=detaillierte Dampflokomotive
|
||||
Passenger Wagon=Passagierwaggon
|
||||
Box Wagon=Güterwaggon
|
||||
Subway Passenger Wagon=U-Bahn-Waggon
|
||||
The wagon's inventory is not empty!=Das Inventar dieses Waggons ist nicht leer!
|
||||
This track can not be changed!=Diese Schiene kann nicht geändert werden!
|
||||
This track can not be rotated!=Diese Schiene kann nicht gedreht werden!
|
||||
This track can not be removed!=Diese Schiene kann nicht entfernt werden!
|
||||
Position is occupied by a train.=Ein Zug steht an dieser Position.
|
||||
There's a Track Circuit Break here.=Hier ist eine Gleisabschnittsgrenze (TCB).
|
||||
There's a Signal Influence Point here.=Hier ist ein Signal-Beeinflussungspunkt.
|
||||
Buffer and Chain Coupler=Schraubenkupplung
|
||||
Scharfenberg Coupler=Scharfenbergkupplung
|
||||
Japanese Train Inter-Wagon Connection=Waggonzwischenverbindung Japanischer Personenzug
|
||||
Can not couple: The couplers of the trains do not match (@1 and @2).=Kann nicht ankuppeln: Die Kupplungen der Züge passen nicht zueinander (@1 und @2)
|
||||
Train ID=Zugnummer
|
||||
<none>=<keine>
|
|
@ -1,146 +0,0 @@
|
|||
# textdomain: advtrains
|
||||
|
||||
# Advtrains Core (unorganized)
|
||||
This wagon is owned by @1, you can't destroy it.=Ce wagon est la propriété de @1, vous ne pouvez pas le détruire.
|
||||
Warning: If you destroy this wagon, you only get some steel back! If you are sure, hold Sneak and left-click the wagon.=Attention: Si vous détruisez ce wagon, vous ne récupérerez que de la ferraille ! Si vous êtes sûr de vous, appuyez la touche "Marcher lentement (Sneak)" et Clic-Gauche.
|
||||
This position is protected!=Cet emplacement est protégé !
|
||||
Can't place: not pointing at node=Placement impossible : ne pointe pas un nœud
|
||||
Can't place: space occupied!=Placement impossible : espace occupé
|
||||
Can't place: protected position!=Placement impossible : emplacement protégé
|
||||
Can't place: Not enough slope items left (@1 required)=Placement impossible : quantité insuffisante de voie pentue (@1 manquant)
|
||||
Can't place: There's no slope of length @1=Placement impossible : il n'y a pas de voie pentue de longueur @1
|
||||
Can't place: no supporting node at upper end.=Placement impossible : pas de nœud d'appui à l'extrémité supérieure
|
||||
Deprecated Track=Voie déconseillée
|
||||
Can't get on: wagon full or doors closed!=Embarquement impossible : le wagon est plein ou ses portes sont closes !
|
||||
Use Sneak+rightclick to bypass closed doors!=Utilisez "Marcher lentement (Sneak)" et Clic-Droit pour franchir les portes closes !
|
||||
Doors are closed! Use Sneak+rightclick to ignore the closed doors and get off!=Portes closes ! Utilisez "Marcher lentement (Sneak)" et Clic-Droit pour franchir les portes et débarquer !
|
||||
Access to @1=Accès à @1
|
||||
You do not have the @1 privilege.=Vous ne possédez pas le privilège "@1".
|
||||
The wagon's inventory is not empty!=Le stock de ce wagon n'est pas vide !
|
||||
Position is occupied by a train.=Cet emplacement est occupé par un train.
|
||||
There's a Track Circuit Break here.=Il y a un "Track Circuit Break" ici.
|
||||
There's a Signal Influence Point here.=Il y a un "Signal Influence Point" ici.
|
||||
|
||||
# Trackworker, rotation, adjustment
|
||||
This node can't be rotated using the trackworker!=Ce nœud ne peut être tourné avec l'outil "Trackworker" !
|
||||
This node can't be changed using the trackworker!=Ce nœud ne peut être modifié avec l'outil "Trackworker" !
|
||||
This track can not be changed!=Cette voie ne peut pas être modifiée !
|
||||
This track can not be rotated!=Cette voie ne peut pas être tournée !
|
||||
This track can not be removed!=Cette voie ne peut pas être enlevée !
|
||||
|
||||
# ATC
|
||||
ATC controller, unconfigured.=Controlleur ATC, non-configuré
|
||||
ATC controller=Controlleur ATC
|
||||
ATC controller, mode @1@nChannel: @2=Controlleur ATC, mode @1@nCanal : @2
|
||||
ATC controller, mode @1@nCommand: @2=Controlleur ATC, mode @1@nCommande : @2
|
||||
Command=Commande
|
||||
Command (on)=Commande (marche)
|
||||
Digiline channel=Canal Digiline
|
||||
ATC Kick command warning: Doors closed=ATC Kick command warning: Doors closed
|
||||
ATC Kick command warning: Train moving=ATC Kick command warning: Train moving
|
||||
ATC Reverse command warning: didn't reverse train, train moving!=Attention : Commande ATC de renversement impossible car le train se déplace !
|
||||
ATC command syntax error: I statement not closed: @1=Erreur de syntaxe de commande ATC : instruction "I" incomplète : @1
|
||||
ATC command parse error: Unknown command: @1=Erreur d'analyse de commande ATC : Commande inconnue : @1
|
||||
|
||||
# Coupling
|
||||
Lock couples=Verrouiller l'accouplement
|
||||
You need to own at least one neighboring wagon to destroy this couple.=Vous devez être propriétaire d'au moins un wagon voisin pour supprimer cet attelage.
|
||||
Buffer and Chain Coupler=Attelage à tampon et vis
|
||||
Scharfenberg Coupler=Attelage Scharfenberg
|
||||
Japanese Train Inter-Wagon Connection=Passage inter-voiture de train Japonais
|
||||
Can not couple: The couplers of the trains do not match (@1 and @2).=Accouplement impossible: les attelages des trains ne concordent pas (@1 et @2).
|
||||
You are not allowed to couple trains without the train_operator privilege.=You are not allowed to couple trains without the train_operator privilege.
|
||||
|
||||
# Clipboard
|
||||
The track you are trying to place the wagon on is not long enough!=La voie sur laquelle vous tentez de placer le wagon est trop courte !
|
||||
The clipboard couldn't access the metadata. Paste failed.=Le presse-papier ne peut accéder aux métadonnées. Échec du collage.
|
||||
The clipboard couldn't access the metadata. Copy failed.=Le presse-papier ne peut accéder aux métadonnées. Échec de la copie.
|
||||
The clipboard is empty.=Le presse-papier est vide.
|
||||
Back of train would end up off track, cancelling.=La fin du train serait hors voie : annulation.
|
||||
No such lua entity!=Pas de telle entité lua !
|
||||
No such wagon: @1=Pas de tel wagon : @1
|
||||
No such train: @1=Pas de tel train : @1
|
||||
Train copied!=Train copié !
|
||||
|
||||
# Protection
|
||||
You are not allowed to build tracks without the track_builder privilege.=Vous ne pouvez pas construire une voie sans le privilège "track_builder"
|
||||
You are not allowed to build near tracks without the track_builder privilege.=Vous ne pouvez pas construire à proximité d'une voie sans le privilège "track_builder" (?)
|
||||
You are not allowed to build tracks at this protected position.=Vous ne pouvez pas construire une voie à cet emplacement protégé
|
||||
You are not allowed to build near tracks at this protected position.=Vous ne pouvez pas construire à proximité d'une voie à cet emplacement protégé
|
||||
You are not allowed to operate turnouts and signals without the railway_operator privilege.=Vous ne pouvez pas actionner les aiguillages ou les signaux (privilège "railway_operator" manquant)
|
||||
|
||||
# Train HUD/Formspecs
|
||||
Speed:=Vitesse :
|
||||
Target:=Destination :
|
||||
Show Inventory=Montrer le stock
|
||||
Select seat:=Choisir le siège
|
||||
Wagon properties=Propriétés du wagon
|
||||
Save wagon properties=Sauvegarder les propriétés du wagon
|
||||
Text displayed outside on train=Texte affiché à l'extérieur du train
|
||||
Text displayed inside train=Texte affiché à l'intérieur du train
|
||||
Line=Ligne
|
||||
Routingcode=Code de routage
|
||||
Get off=Débarquer
|
||||
Get off (forced)=Débarquer (de force)
|
||||
(Doors closed)=(Portes closes)
|
||||
|
||||
# General
|
||||
Save=Sauvegarder
|
||||
|
||||
# Line automation
|
||||
Station Code=Code de Station
|
||||
Station Name=Nom de Station
|
||||
Door Delay=Durée d'ouverture des portes
|
||||
Door Side=Door Side
|
||||
Dep. Speed=Vitesse de départ
|
||||
Stop Time=Durée d'arrêt
|
||||
|
||||
# Items
|
||||
Track Worker Tool@n@nLeft-click: change rail type (straight/curve/switch)@nRight-click: rotate rail/bumper/signal/etc.=Outil "Trackworker"@n@nClic-Gauche : change le type de rail (droit/courbé/aiguillage)@n@nClic-Droit : tourne le rail/butoir/signal/etc...
|
||||
Passive Component Naming Tool@n@nRight-click to name a passive component.=Outil de nommage de composant passif@n@nClic-Droit pour nommer un composant passif.
|
||||
Train copy/paste tool@n@nLeft-click: copy train@nRight-click: paste train=Outil de copie/collage de train@n@nClic-Gauche : copie@n@nClic-Droit : collage
|
||||
Track=Voie
|
||||
Perpendicular Diamond Crossing Track=Croisement perpendiculaire
|
||||
Diagonal Diamond Crossing Track=Croisement diagonal
|
||||
90+Angle Diamond Crossing Track=Croisement perpendiculo-diagonal
|
||||
Y-turnout=Embranchement en Y
|
||||
3-way turnout=Embranchement triple
|
||||
Unloading Track=Voie de Déchargement
|
||||
Loading Track=Voie de Chargement
|
||||
Bumper=Heurtoir
|
||||
Detector Rail=Voie détectrice
|
||||
@1 Slope=Pente @1
|
||||
@1 Platform (low)=Quai @1 (bas)
|
||||
@1 Platform (high)=Quai @1 (haut)
|
||||
@1 Platform (low, 45 degree)=Quai @1 (bas, 45°)
|
||||
@1 Platform (45 degree)=Quai @1 (haut, 45°)
|
||||
Lampless Signal=Sémaphore
|
||||
Signal=Signal
|
||||
Wallmounted Signal (l)=Signal mural (gauche)
|
||||
Wallmounted Signal (r)=Signal mural (droit)
|
||||
Wallmounted Signal (t)=Signal mural (plafond)
|
||||
Andrew's Cross=Croix de Saint André
|
||||
Boiler=Chaudière à vapeur
|
||||
driver's cab=Cabine de pilotage
|
||||
Wheel=Roue
|
||||
Chimney=Cheminée
|
||||
|
||||
# Seats
|
||||
Default Seat=Siège par défaut
|
||||
Default Seat (driver stand)=Siège par défaut (poste de pilotage)
|
||||
Driver stand=Poste de pilotage
|
||||
Driver Stand (left)=Poste de pilotage (gauche)
|
||||
Driver Stand (right)=Poste de pilotage (droit)
|
||||
|
||||
# Wagon/engine types
|
||||
Industrial Train Engine=Locomotive industrielle
|
||||
Big Industrial Train Engine=Grosse locomotive industrielle
|
||||
Industrial tank wagon=Wagon-citerne industriel
|
||||
Industrial wood wagon=Wagon grumier industriel
|
||||
Japanese Train Engine=Motrice Japonaise
|
||||
Japanese Train Wagon=Voiture Japonaise
|
||||
Steam Engine=Locomotive à vapeur
|
||||
Detailed Steam Engine=Locomotive à vapeur complexe
|
||||
Passenger Wagon=Voiture passager
|
||||
Box Wagon=Wagon de frêt
|
||||
Subway Passenger Wagon=Voiture de Métropolitain
|
|
@ -1,146 +0,0 @@
|
|||
# textdomain: advtrains
|
||||
|
||||
# Advtrains Core (unorganized)
|
||||
This wagon is owned by @1, you can't destroy it.=这是 @1 的车厢,您不能摧毁它。
|
||||
Warning: If you destroy this wagon, you only get some steel back! If you are sure, hold Sneak and left-click the wagon.=警告:如果您摧毁此车厢,您只能拿到一些钢方块。如果您确定要摧毁这节车厢,请按潜行键并左键单击此车厢。
|
||||
This position is protected!=这里已被保护。
|
||||
Can't place: not pointing at node=无法放置:您没有选择任何方块。
|
||||
Can't place: space occupied!=无法放置:此区域已被占用。
|
||||
Can't place: protected position!=无法放置:此区域已被保护。
|
||||
Can't place: Not enough slope items left (@1 required)=无法放置:您没有足够的铁路斜坡放置工具 (您总共需要@1个)
|
||||
Can't place: There's no slope of length @1=无法放置:advtrains 不支持长度为@1米的斜坡。
|
||||
Can't place: no supporting node at upper end.=无法放置:较高端没有支撑方块。
|
||||
Deprecated Track=请不要使用
|
||||
Can't get on: wagon full or doors closed!=无法上车:车门已关闭或车厢已满。
|
||||
Use Sneak+rightclick to bypass closed doors!=请使用潜行+右键上车。
|
||||
Doors are closed! Use Sneak+rightclick to ignore the closed doors and get off!=车门已关闭,请使用潜行+右键单击下车。
|
||||
Access to @1=可前往@1
|
||||
You do not have the @1 privilege.=您没有“@1”权限。
|
||||
The wagon's inventory is not empty!=The wagon's inventory is not empty!
|
||||
Position is occupied by a train.=Position is occupied by a train.
|
||||
There's a Track Circuit Break here.=There's a Track Circuit Break here.
|
||||
There's a Signal Influence Point here.=There's a Signal Influence Point here.
|
||||
|
||||
# Trackworker, rotation, adjustment
|
||||
This node can't be rotated using the trackworker!=您不能使用铁路调整工具旋转这个方块。
|
||||
This node can't be changed using the trackworker!=您不能使用铁路调整工具调整这个方块。
|
||||
This track can not be changed!=您不能调整这段轨道。
|
||||
This track can not be rotated!=您不能旋转这段轨道。
|
||||
This track can not be removed!=您不能移除这段轨道。
|
||||
|
||||
# ATC
|
||||
ATC controller, unconfigured.=ATC 控制器 (未配置)
|
||||
ATC controller=ATC 控制器
|
||||
ATC controller, mode @1@nChannel: @2=ATC 控制器@n模式:@1@n频道:@2
|
||||
ATC controller, mode @1@nCommand: @2=ATC 控制器@n模式:@1@n命令:@2
|
||||
Command=命令
|
||||
Command (on)=命令 (激活时)
|
||||
Digiline channel=Digiline 频道
|
||||
ATC Kick command warning: Doors closed=ATC Kick command warning: Doors closed
|
||||
ATC Kick command warning: Train moving=ATC Kick command warning: Train moving
|
||||
ATC Reverse command warning: didn't reverse train, train moving!=ATC 警告:未执行“R”命令,火车在移动
|
||||
ATC command syntax error: I statement not closed: @1=ATC 语法错误:“I”命令不完整:@1
|
||||
ATC command parse error: Unknown command: @1=ATC 语法错误:未知命令:@1
|
||||
|
||||
# Coupling
|
||||
Lock couples=锁定连接处
|
||||
You need to own at least one neighboring wagon to destroy this couple.=您必须至少拥有其中一节车厢才能分开这两节车厢。
|
||||
Buffer and Chain Coupler=链式车钩
|
||||
Scharfenberg Coupler=Scharfenberg 式车钩
|
||||
Japanese Train Inter-Wagon Connection=日本火车车钩
|
||||
Can not couple: The couplers of the trains do not match (@1 and @2).=您无法连接这两节车厢:这两节车厢使用不同的车钩 (@1和@2)。
|
||||
You are not allowed to couple trains without the train_operator privilege.=您没有“train_operator”权限,不能连接这两节车厢。
|
||||
|
||||
# Clipboard
|
||||
The track you are trying to place the wagon on is not long enough!=轨道太短。
|
||||
The clipboard couldn't access the metadata. Paste failed.=无法粘贴:剪贴板无法访问元数据。
|
||||
The clipboard couldn't access the metadata. Copy failed.=无法复制:剪贴板无法访问元数据。
|
||||
The clipboard is empty.=剪贴板是空的。
|
||||
Back of train would end up off track, cancelling.=火车后部不在轨道上。
|
||||
No such lua entity!=您没有指向一个可以用火车复制工具复制的物体。
|
||||
No such wagon: @1=ID 为“@1”的车厢不存在。
|
||||
No such train: @1=ID 为“@1”的列车不存在。
|
||||
Train copied!=已复制
|
||||
|
||||
# Protection
|
||||
You are not allowed to build tracks without the track_builder privilege.=您没有“train_operator”权限,不能在这里建造铁路。
|
||||
You are not allowed to build near tracks without the track_builder privilege.=您没有“train_operator”权限,不能在铁路附近建任何东西。
|
||||
You are not allowed to build tracks at this protected position.=这里已被保护,您不能在这里建造铁路。
|
||||
You are not allowed to build near tracks at this protected position.=这里已被保护,您不能在这里的铁路附近建任何东西。
|
||||
You are not allowed to operate turnouts and signals without the railway_operator privilege.=您没有“railway_operator”权限,不能控制铁路设施。
|
||||
|
||||
# Train HUD/Formspecs
|
||||
Speed:=速度
|
||||
Target:=目标速度
|
||||
Show Inventory=显示物品栏
|
||||
Select seat:=请选择座位
|
||||
Wagon properties=车厢属性
|
||||
Save wagon properties=保存车厢属性
|
||||
Text displayed outside on train=车厢外部显示
|
||||
Text displayed inside train=车厢内部显示
|
||||
Line=火车线路
|
||||
Routingcode=路由码
|
||||
Get off=下车
|
||||
Get off (forced)=强制下车
|
||||
(Doors closed)=(车门已关闭)
|
||||
|
||||
# General
|
||||
Save=保存
|
||||
|
||||
# Line automation
|
||||
Station Code=车站代码
|
||||
Station Name=车站名称
|
||||
Door Delay=车门关闭时间
|
||||
Door Side=Door Side
|
||||
Dep. Speed=出发速度
|
||||
Stop Time=停站时间
|
||||
|
||||
# Items
|
||||
Track Worker Tool@n@nLeft-click: change rail type (straight/curve/switch)@nRight-click: rotate rail/bumper/signal/etc.=铁路调整工具@n@n左键单击:切换轨道类型@n右键单击:旋转方块
|
||||
Passive Component Naming Tool@n@nRight-click to name a passive component.=被动元件命名工具@n@n右键单击命名所选元件
|
||||
Train copy/paste tool@n@nLeft-click: copy train@nRight-click: paste train=火车复制工具@n@n左键单击:复制@n右键单击:粘帖
|
||||
Track=轨道
|
||||
Perpendicular Diamond Crossing Track=垂直交叉轨道
|
||||
Diagonal Diamond Crossing Track=交叉轨道
|
||||
90+Angle Diamond Crossing Track=交叉轨道 (其中一条轨道与坐标轴平行)
|
||||
Y-turnout=对称道岔
|
||||
3-way turnout=三开道岔
|
||||
Unloading Track=卸货轨道
|
||||
Loading Track=装货轨道
|
||||
Bumper=保险杠
|
||||
Detector Rail=探测轨道
|
||||
@1 Slope=@1斜坡
|
||||
@1 Platform (low)=较低的@1站台
|
||||
@1 Platform (high)=较高的@1站台
|
||||
@1 Platform (low, 45 degree)=较低的@1站台 (45°)
|
||||
@1 Platform (45 degree)=较高的@1站台 (45°)
|
||||
Lampless Signal=臂板信号机
|
||||
Signal=信号灯
|
||||
Wallmounted Signal (l)=壁挂式信号灯 (左侧)
|
||||
Wallmounted Signal (r)=壁挂式信号灯 (右侧)
|
||||
Wallmounted Signal (t)=悬挂式信号灯
|
||||
Andrew's Cross=铁路道口信号灯
|
||||
Boiler=锅炉
|
||||
driver's cab=驾驶室
|
||||
Wheel=车轮
|
||||
Chimney=烟囱
|
||||
|
||||
# Seats
|
||||
Default Seat=默认座位
|
||||
Default Seat (driver stand)=默认座位 (司机座位)
|
||||
Driver stand=司机座位
|
||||
Driver Stand (left)=左侧司机座位
|
||||
Driver Stand (right)=右侧司机座位
|
||||
|
||||
# Wagon/engine types
|
||||
Industrial Train Engine=工业用火车头
|
||||
Big Industrial Train Engine=大型工业用火车头
|
||||
Industrial tank wagon=液体运输车厢
|
||||
Industrial wood wagon=木材运输车厢
|
||||
Japanese Train Engine=高速列车车头
|
||||
Japanese Train Wagon=高速列车车厢
|
||||
Steam Engine=蒸汽机车
|
||||
Detailed Steam Engine=精细的蒸汽机车
|
||||
Passenger Wagon=客车
|
||||
Box Wagon=货运车厢
|
||||
Subway Passenger Wagon=地铁车厢
|
|
@ -1,146 +0,0 @@
|
|||
# textdomain: advtrains
|
||||
|
||||
# Advtrains Core (unorganized)
|
||||
This wagon is owned by @1, you can't destroy it.=這是 @1 的車廂,您不能摧毀它。
|
||||
Warning: If you destroy this wagon, you only get some steel back! If you are sure, hold Sneak and left-click the wagon.=警告:如果您摧毀此車廂,您只能拿到一些鋼方塊。如果您確定要摧毀這節車廂,請按潛行鍵並左鍵單擊此車廂。
|
||||
This position is protected!=這裡已被保護。
|
||||
Can't place: not pointing at node=無法放置:您沒有選擇任何方塊。
|
||||
Can't place: space occupied!=無法放置:此區域已被佔用。
|
||||
Can't place: protected position!=無法放置:此區域已被保護。
|
||||
Can't place: Not enough slope items left (@1 required)=無法放置:您沒有足夠的鐵路斜坡放置工具 (您總共需要@1個)
|
||||
Can't place: There's no slope of length @1=無法放置:advtrains 不支援長度為@1米的斜坡。
|
||||
Can't place: no supporting node at upper end.=無法放置:較高階沒有支撐方塊。
|
||||
Deprecated Track=請不要使用
|
||||
Can't get on: wagon full or doors closed!=無法上車:車門已關閉或車廂已滿。
|
||||
Use Sneak+rightclick to bypass closed doors!=請使用潛行+右鍵上車。
|
||||
Doors are closed! Use Sneak+rightclick to ignore the closed doors and get off!=車門已關閉,請使用潛行+右鍵單擊下車。
|
||||
Access to @1=可前往@1
|
||||
You do not have the @1 privilege.=您沒有「@1」許可權。
|
||||
The wagon's inventory is not empty!=The wagon's inventory is not empty!
|
||||
Position is occupied by a train.=Position is occupied by a train.
|
||||
There's a Track Circuit Break here.=There's a Track Circuit Break here.
|
||||
There's a Signal Influence Point here.=There's a Signal Influence Point here.
|
||||
|
||||
# Trackworker, rotation, adjustment
|
||||
This node can't be rotated using the trackworker!=您不能使用鐵路調整工具旋轉這個方塊。
|
||||
This node can't be changed using the trackworker!=您不能使用鐵路調整工具調整這個方塊。
|
||||
This track can not be changed!=您不能調整這段軌道。
|
||||
This track can not be rotated!=您不能旋轉這段軌道。
|
||||
This track can not be removed!=您不能移除這段軌道。
|
||||
|
||||
# ATC
|
||||
ATC controller, unconfigured.=ATC 控制器 (未配置)
|
||||
ATC controller=ATC 控制器
|
||||
ATC controller, mode @1@nChannel: @2=ATC 控制器@n模式:@1@n頻道:@2
|
||||
ATC controller, mode @1@nCommand: @2=ATC 控制器@n模式:@1@n命令:@2
|
||||
Command=命令
|
||||
Command (on)=命令 (啟用時)
|
||||
Digiline channel=Digiline 頻道
|
||||
ATC Kick command warning: Doors closed=ATC Kick command warning: Doors closed
|
||||
ATC Kick command warning: Train moving=ATC Kick command warning: Train moving
|
||||
ATC Reverse command warning: didn't reverse train, train moving!=ATC 警告:未執行「R」命令,火車在移動
|
||||
ATC command syntax error: I statement not closed: @1=ATC 語法錯誤:「I」命令不完整:@1
|
||||
ATC command parse error: Unknown command: @1=ATC 語法錯誤:未知命令:@1
|
||||
|
||||
# Coupling
|
||||
Lock couples=鎖定連結處
|
||||
You need to own at least one neighboring wagon to destroy this couple.=您必須至少擁有其中一節車廂才能分開這兩節車廂。
|
||||
Buffer and Chain Coupler=鏈式連結器
|
||||
Scharfenberg Coupler=Scharfenberg 式連結器
|
||||
Japanese Train Inter-Wagon Connection=日本火車連結器
|
||||
Can not couple: The couplers of the trains do not match (@1 and @2).=您無法連結這兩節車廂:這兩節車廂使用不同的連結器 (@1和@2)。
|
||||
You are not allowed to couple trains without the train_operator privilege.=您沒有「train_operator」許可權,不能連結這兩節車廂。
|
||||
|
||||
# Clipboard
|
||||
The track you are trying to place the wagon on is not long enough!=軌道太短。
|
||||
The clipboard couldn't access the metadata. Paste failed.=無法貼上:剪貼簿無法訪問元資料。
|
||||
The clipboard couldn't access the metadata. Copy failed.=無法複製:剪貼簿無法訪問元資料。
|
||||
The clipboard is empty.=剪貼簿是空的。
|
||||
Back of train would end up off track, cancelling.=火車後部不在軌道上。
|
||||
No such lua entity!=您沒有指向一個可以用火車複製工具複製的物體。
|
||||
No such wagon: @1=ID 為「@1」的車廂不存在。
|
||||
No such train: @1=ID 為「@1」的列車不存在。
|
||||
Train copied!=已複製
|
||||
|
||||
# Protection
|
||||
You are not allowed to build tracks without the track_builder privilege.=您沒有「train_operator」許可權,不能在這裡建造鐵路。
|
||||
You are not allowed to build near tracks without the track_builder privilege.=您沒有「train_operator」許可權,不能在鐵路附近建任何東西。
|
||||
You are not allowed to build tracks at this protected position.=這裡已被保護,您不能在這裡建造鐵路。
|
||||
You are not allowed to build near tracks at this protected position.=這裡已被保護,您不能在這裡的鐵路附近建任何東西。
|
||||
You are not allowed to operate turnouts and signals without the railway_operator privilege.=您沒有「railway_operator」許可權,不能控制鐵路設施。
|
||||
|
||||
# Train HUD/Formspecs
|
||||
Speed:=速度
|
||||
Target:=目標速度
|
||||
Show Inventory=顯示物品欄
|
||||
Select seat:=請選擇座位
|
||||
Wagon properties=車廂屬性
|
||||
Save wagon properties=儲存車廂屬性
|
||||
Text displayed outside on train=車廂外部顯示
|
||||
Text displayed inside train=車廂內部顯示
|
||||
Line=火車線路
|
||||
Routingcode=路由碼
|
||||
Get off=下車
|
||||
Get off (forced)=強制下車
|
||||
(Doors closed)=(車門已關閉)
|
||||
|
||||
# General
|
||||
Save=儲存
|
||||
|
||||
# Line automation
|
||||
Station Code=車站碼
|
||||
Station Name=車站名稱
|
||||
Door Delay=車門關閉時間
|
||||
Door Side=Door Side
|
||||
Dep. Speed=出發速度
|
||||
Stop Time=停站時間
|
||||
|
||||
# Items
|
||||
Track Worker Tool@n@nLeft-click: change rail type (straight/curve/switch)@nRight-click: rotate rail/bumper/signal/etc.=鐵路調整工具@n@n左鍵單擊:切換軌道型別@n右鍵單擊:旋轉方塊
|
||||
Passive Component Naming Tool@n@nRight-click to name a passive component.=被動元件命名工具@n@n右鍵單擊命名所選元件
|
||||
Train copy/paste tool@n@nLeft-click: copy train@nRight-click: paste train=火車複製工具@n@n左鍵單擊:複製@n右鍵單擊:粘帖
|
||||
Track=軌道
|
||||
Perpendicular Diamond Crossing Track=垂直交叉軌道
|
||||
Diagonal Diamond Crossing Track=交叉軌道
|
||||
90+Angle Diamond Crossing Track=交叉軌道 (其中一條軌道與座標軸平行)
|
||||
Y-turnout=對稱道岔
|
||||
3-way turnout=三開道岔
|
||||
Unloading Track=卸貨軌道
|
||||
Loading Track=裝貨軌道
|
||||
Bumper=保險槓
|
||||
Detector Rail=探測軌道
|
||||
@1 Slope=@1斜坡
|
||||
@1 Platform (low)=較低的@1月臺
|
||||
@1 Platform (high)=較高的@1月臺
|
||||
@1 Platform (low, 45 degree)=較低的@1月臺 (45°)
|
||||
@1 Platform (45 degree)=較高的@1月臺 (45°)
|
||||
Lampless Signal=臂木式號誌機
|
||||
Signal=色燈號誌機
|
||||
Wallmounted Signal (l)=壁掛式色燈號誌機 (左側)
|
||||
Wallmounted Signal (r)=壁掛式色燈號誌機 (右側)
|
||||
Wallmounted Signal (t)=懸掛式色燈號誌機
|
||||
Andrew's Cross=平交道號誌燈
|
||||
Boiler=鍋爐
|
||||
driver's cab=駕駛室
|
||||
Wheel=車輪
|
||||
Chimney=煙囪
|
||||
|
||||
# Seats
|
||||
Default Seat=預設座位
|
||||
Default Seat (driver stand)=預設座位 (司機座位)
|
||||
Driver stand=司機座位
|
||||
Driver Stand (left)=左側司機座位
|
||||
Driver Stand (right)=右側司機座位
|
||||
|
||||
# Wagon/engine types
|
||||
Industrial Train Engine=工業用火車頭
|
||||
Big Industrial Train Engine=大型工業用火車頭
|
||||
Industrial tank wagon=液體運輸車廂
|
||||
Industrial wood wagon=木材運輸車廂
|
||||
Japanese Train Engine=高速列車車頭
|
||||
Japanese Train Wagon=高速列車車廂
|
||||
Steam Engine=蒸汽機車
|
||||
Detailed Steam Engine=精細的蒸汽機車
|
||||
Passenger Wagon=客車
|
||||
Box Wagon=貨運車廂
|
||||
Subway Passenger Wagon=地鐵車廂
|
|
@ -1,638 +0,0 @@
|
|||
#!/usr/bin/tclsh
|
||||
package require Tk
|
||||
|
||||
# Auxiliary functions
|
||||
proc maybe_lindex {lst idx fallback} {
|
||||
set val [lindex $lst $idx]
|
||||
if {$val eq {}} {
|
||||
return $fallback
|
||||
} else {
|
||||
return $val
|
||||
}
|
||||
}
|
||||
|
||||
proc firstupper {str} {
|
||||
return [string cat [string toupper [string index $str 0]] [string range $str 1 end]]
|
||||
}
|
||||
|
||||
# CLI arguments
|
||||
# NOTE: This will likely be changed in the future
|
||||
set translationDomain [maybe_lindex $argv 0 "advtrains"]
|
||||
set translationDir [maybe_lindex $argv 1 "."]
|
||||
|
||||
# Translation file I/O, etc
|
||||
|
||||
set translationTemplatePath [file join $translationDir "template.txt"]
|
||||
|
||||
proc translationFilePaths {} {
|
||||
global translationDir translationDomain
|
||||
return [glob -path [file join $translationDir $translationDomain] ".*.tr"]
|
||||
}
|
||||
|
||||
proc readTranslationTemplate {} {
|
||||
global translationTemplate translationTemplatePath
|
||||
set translationTemplate [list]
|
||||
set handle [open $translationTemplatePath "r"]
|
||||
fconfigure $handle -translation lf
|
||||
while {[gets $handle line] >= 0} {
|
||||
if {$line eq ""} {
|
||||
lappend translationTemplate $line
|
||||
} elseif {[string match {#*} $line]} {
|
||||
lappend translationTemplate $line
|
||||
} elseif {[regexp {^(.+[^@])=.+$} $line x str]} {
|
||||
lappend translationTemplate $str
|
||||
}
|
||||
}
|
||||
close $handle
|
||||
}
|
||||
|
||||
proc readTranslationFiles {} {
|
||||
global translationData translationLangs
|
||||
array set translationData [list]
|
||||
set translationLangs [list]
|
||||
foreach fn [translationFilePaths] {
|
||||
if {[regexp {\.([^.]+)\.tr$} $fn x lang]} {
|
||||
set handle [open $fn "r"]
|
||||
fconfigure $handle -translation lf
|
||||
while {[gets $handle line] >= 0} {
|
||||
if {[regexp {^([^#].+[^@])=(.+)$} $line x ori tr]} {
|
||||
set translationData($lang,$ori) $tr
|
||||
}
|
||||
}
|
||||
lappend translationLangs $lang
|
||||
close $handle
|
||||
}
|
||||
}
|
||||
set translationLangs [lsort $translationLangs]
|
||||
}
|
||||
|
||||
proc readTranslations {} {
|
||||
readTranslationTemplate
|
||||
readTranslationFiles
|
||||
}
|
||||
|
||||
proc writeTranslationTemplate {} {
|
||||
global translationTemplate translationTemplatePath
|
||||
set handle [open $translationTemplatePath "w"]
|
||||
fconfigure $handle -translation lf
|
||||
foreach line $translationTemplate {
|
||||
if {$line eq ""} {
|
||||
puts $handle ""
|
||||
} elseif {[string match {#*} $line]} {
|
||||
puts $handle $line
|
||||
} else {
|
||||
puts $handle "$line=$line"
|
||||
}
|
||||
}
|
||||
close $handle
|
||||
}
|
||||
|
||||
proc writeTranslationFiles {} {
|
||||
global translationDir translationDomain translationData translationLangs translationTemplate
|
||||
foreach lang $translationLangs {
|
||||
set handle [open [file join $translationDir "$translationDomain.$lang.tr"] "w"]
|
||||
fconfigure $handle -translation lf
|
||||
foreach i $translationTemplate {
|
||||
if {$i eq ""} {
|
||||
puts $handle ""
|
||||
} elseif {[string match {#*} $i]} {
|
||||
puts $handle $i
|
||||
} else {
|
||||
puts $handle [format "%s=%s" $i [getTranslationString $lang $i]]
|
||||
}
|
||||
}
|
||||
close $handle
|
||||
}
|
||||
}
|
||||
|
||||
proc writeTranslations {} {
|
||||
writeTranslationTemplate
|
||||
writeTranslationFiles
|
||||
}
|
||||
|
||||
proc hasTranslationString {lang str} {
|
||||
return [expr {[getTranslationString $lang $str] ne $str}]
|
||||
}
|
||||
|
||||
proc maybeGetTranslationString {lang str} {
|
||||
set tr [getTranslationString $lang $str]
|
||||
if {$tr eq $str} {
|
||||
return {}
|
||||
} else {
|
||||
return $tr
|
||||
}
|
||||
}
|
||||
|
||||
proc getTranslationString {lang str} {
|
||||
global translationData
|
||||
if {[info exists translationData($lang,$str)]} {
|
||||
return $translationData($lang,$str)
|
||||
} else {
|
||||
return $str
|
||||
}
|
||||
}
|
||||
|
||||
proc setTranslationString {lang ori tr} {
|
||||
global translationData
|
||||
set translationData($lang,$ori) $tr
|
||||
}
|
||||
|
||||
proc rewordTranslationString {old new} {
|
||||
global translationData translationLangs
|
||||
foreach lang $translationLangs {
|
||||
if {[hasTranslationString $lang $old]} {
|
||||
setTranslationString $lang $new [getTranslationString $lang $old]
|
||||
} else {
|
||||
setTranslationString $lang $new $new
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# GUI helpers
|
||||
proc gAddTab {basename title elems dummies} {
|
||||
global gMainNotebook
|
||||
gAddFrame $basename $elems $dummies
|
||||
$gMainNotebook add "$gMainNotebook.$basename" -text $title
|
||||
}
|
||||
|
||||
proc gAddFrame {basename elems dummies} {
|
||||
global gMainNotebook
|
||||
set varbase [string cat "g" [firstupper $basename]]
|
||||
set varname "${varbase}Frame"
|
||||
set pathname "$gMainNotebook.$basename"
|
||||
global $varname
|
||||
set $varname $pathname
|
||||
ttk::frame $pathname -padding 5
|
||||
foreach i $elems {
|
||||
set varname [string cat $varbase [firstupper $i]]
|
||||
global $varname
|
||||
set $varname "$pathname.$i"
|
||||
}
|
||||
foreach i $dummies {
|
||||
set varname [string cat $varbase [firstupper $i]]
|
||||
global $varname
|
||||
set $varname {}
|
||||
}
|
||||
}
|
||||
|
||||
proc gReloadTranslations {} {
|
||||
readTranslations
|
||||
gTrLoadTranslations
|
||||
gTmLoadTranslations
|
||||
}
|
||||
|
||||
proc gAddMenu {varname parent menuname entries} {
|
||||
global $varname
|
||||
set path "${parent}.${menuname}"
|
||||
set $varname $path
|
||||
$parent configure -menu [menu $path -tearoff false]
|
||||
foreach i $entries {
|
||||
$path add {*}$i
|
||||
}
|
||||
return $parent
|
||||
}
|
||||
set gMenuItemNotImplemented [list command -state disabled -label "(Not implemented)"]
|
||||
|
||||
proc gNotImplemented {args} {
|
||||
tk_messageBox -message "Not implemented" -icon error -type ok
|
||||
}
|
||||
|
||||
# Main window
|
||||
|
||||
set gMainFrame ".f"
|
||||
set gMainFrameWidgetCount 0
|
||||
foreach i [list readBtn writeBtn notebookTopSeparator notebook] {
|
||||
set [string cat "gMain" [firstupper $i]] "$gMainFrame.$i"
|
||||
}
|
||||
|
||||
wm title . "Advtrains Translation File Editor"
|
||||
grid rowconfigure . 0 -weight 1
|
||||
grid columnconfigure . 0 -weight 1
|
||||
|
||||
ttk::frame $gMainFrame
|
||||
grid $gMainFrame -column 0 -row 0 -sticky nsew
|
||||
grid rowconfigure $gMainFrame 2 -weight 1
|
||||
|
||||
foreach i [list \
|
||||
[ttk::button $gMainReadBtn -text "Reload translation files" -command gReloadTranslations] \
|
||||
[ttk::button $gMainWriteBtn -text "Write changes" -command writeTranslations] \
|
||||
] {
|
||||
grid $i -column $gMainFrameWidgetCount -row 0 -sticky ns
|
||||
incr gMainFrameWidgetCount
|
||||
}
|
||||
|
||||
grid columnconfigure $gMainFrame $gMainFrameWidgetCount -weight 1
|
||||
|
||||
ttk::separator $gMainNotebookTopSeparator -orient horizontal
|
||||
grid $gMainNotebookTopSeparator -column 0 -row 1 -columnspan [expr {1+$gMainFrameWidgetCount}] -sticky ew
|
||||
|
||||
ttk::notebook $gMainNotebook
|
||||
grid $gMainNotebook -column 0 -row 2 -columnspan [expr {1+$gMainFrameWidgetCount}] -sticky nsew
|
||||
|
||||
# Translation Manager
|
||||
# FIXME?: it seems like Tcl requires -textvariable globals to be set first before they are accessible
|
||||
|
||||
gAddTab tr "Translations" \
|
||||
[list langSelect refLangSelect readBtn writeBtn treeviewFrame origTextLabel origTextField translatedTextLabel translatedTextField refTextLabel refTextField] \
|
||||
[list langValue refLangValue origTextValue translatedTextValue refTextValue]
|
||||
set gTrTreeview "$gTrTreeviewFrame.main"
|
||||
set gTrTreeviewScrollbar "$gTrTreeviewFrame.scrollbar"
|
||||
|
||||
grid rowconfigure $gTrFrame 0 -weight 1
|
||||
grid columnconfigure $gTrFrame 2 -weight 1
|
||||
|
||||
ttk::frame $gTrTreeviewFrame -borderwidth 1 -relief sunken
|
||||
grid $gTrTreeviewFrame -column 0 -row 0 -columnspan 3 -sticky nsew
|
||||
grid rowconfigure $gTrTreeviewFrame 0 -weight 1
|
||||
grid columnconfigure $gTrTreeviewFrame 0 -weight 1
|
||||
ttk::treeview $gTrTreeview -selectmode browse -columns {translation} -yscrollcommand {$gTrTreeviewScrollbar set}
|
||||
grid $gTrTreeview -column 0 -row 0 -sticky nsew
|
||||
bind $gTrTreeview <<TreeviewSelect>> gTrTreeviewSelectionCallback
|
||||
ttk::scrollbar $gTrTreeviewScrollbar -orient vertical -command {$gTrTreeview yview}
|
||||
grid $gTrTreeviewScrollbar -column 1 -row 0 -sticky ns
|
||||
$gTrTreeview heading #0 -text "Original text"
|
||||
|
||||
lmap i [list \
|
||||
[list \
|
||||
[ttk::label $gTrOrigTextLabel -text "Original" -anchor w] \
|
||||
{} \
|
||||
[ttk::entry $gTrOrigTextField -state readonly -textvariable gTrOrigTextValue] \
|
||||
] \
|
||||
[list \
|
||||
[ttk::label $gTrTranslatedTextLabel -text "Translation" -anchor w] \
|
||||
[ttk::combobox $gTrLangSelect -exportselection false -state readonly -textvariable gTrLangValue] \
|
||||
[ttk::entry $gTrTranslatedTextField -textvariable gTrTranslatedTextValue] \
|
||||
] \
|
||||
[list \
|
||||
[ttk::label $gTrRefTextLabel -text "Reference" -anchor w] \
|
||||
[ttk::combobox $gTrRefLangSelect -exportselection false -state readonly -textvariable gTrRefLangValue] \
|
||||
[ttk::entry $gTrRefTextField -state readonly -textvariable gTrRefTextValue] \
|
||||
] \
|
||||
] row [list 1 2 3] {
|
||||
lmap item $i col [list 0 1 2] {
|
||||
if {$item eq ""} {
|
||||
continue
|
||||
}
|
||||
grid $item -column $col -row $row -sticky nswe
|
||||
}
|
||||
grid rowconfigure $gTrFrame $row -uniform bottom
|
||||
incr gTrRowCount
|
||||
}
|
||||
|
||||
bind $gTrLangSelect <<ComboboxSelected>> gTrLoadTranslationsToTreeview
|
||||
trace add variable gTrTranslatedTextValue write gTrApplyTranslationString
|
||||
bind $gTrRefLangSelect <<ComboboxSelected>> gTrTreeviewSelectionCallback
|
||||
|
||||
proc gTrLoadTranslationsToTreeview {} {
|
||||
global translationTemplate gTrTreeview gTrLangValue
|
||||
$gTrTreeview heading translation -text "Translation: $gTrLangValue"
|
||||
set prevFocus [$gTrTreeview item [$gTrTreeview focus] -text]
|
||||
array set openedSections [list]
|
||||
foreach i [$gTrTreeview children {}] {
|
||||
if {[$gTrTreeview item $i -open]} {
|
||||
set openedSections([$gTrTreeview item $i -text]) 1
|
||||
}
|
||||
}
|
||||
$gTrTreeview delete [$gTrTreeview children {}]
|
||||
set parent {}
|
||||
foreach i [lrange $translationTemplate 1 end] {
|
||||
if {[regexp {^\#+\s*(.+)} $i x comment]} {
|
||||
set parent [$gTrTreeview insert {} end -text $comment -tags {notranslate}]
|
||||
if {[info exists openedSections($comment)]} {
|
||||
$gTrTreeview item $parent -open true
|
||||
}
|
||||
if {$comment eq $prevFocus} {
|
||||
$gTrTreeview focus $parent
|
||||
$gTrTreeview selection set $parent
|
||||
}
|
||||
} elseif {$i ne ""} {
|
||||
set last [$gTrTreeview insert $parent end -text $i -values [list [maybeGetTranslationString $gTrLangValue $i]]]
|
||||
if {$i eq $prevFocus} {
|
||||
$gTrTreeview focus $last
|
||||
$gTrTreeview selection set $last
|
||||
}
|
||||
}
|
||||
}
|
||||
gTrTreeviewSelectionCallback
|
||||
}
|
||||
|
||||
proc gTrTreeviewSelectionCallback {} {
|
||||
global gTrOrigTextValue gTrTreeview gTrLangSelect gTrLangValue gTrRefLangSelect gTrRefLangValue gTrTranslatedTextField gTrTranslatedTextValue gTrRefTextField gTrRefTextValue
|
||||
set focused [$gTrTreeview focus]
|
||||
set gTrOrigTextValue [$gTrTreeview item $focused -text]
|
||||
if {$focused eq ""} {
|
||||
$gTrTranslatedTextField state disabled
|
||||
$gTrRefTextField state disabled
|
||||
set gTrTranslatedTextValue "Select an entry to translate"
|
||||
set gTrRefTextValue ""
|
||||
} elseif {[$gTrTreeview tag has notranslate $focused]} {
|
||||
$gTrTranslatedTextField state disabled
|
||||
$gTrRefTextField state disabled
|
||||
set gTrTranslatedTextValue "Category names cannot be translated"
|
||||
set gTrRefTextValue ""
|
||||
} else {
|
||||
$gTrTranslatedTextField state !disabled
|
||||
set gTrTranslatedTextValue [maybeGetTranslationString $gTrLangValue $gTrOrigTextValue]
|
||||
set gTrRefTextValue [maybeGetTranslationString $gTrRefLangValue $gTrOrigTextValue]
|
||||
if {$gTrRefLangValue eq ""} {
|
||||
$gTrRefTextField state disabled
|
||||
set gTrRefTextValue ""
|
||||
} elseif {$gTrRefTextValue eq ""} {
|
||||
$gTrRefTextField state disabled
|
||||
set gTrRefTextValue "The selected string is not yet translated to the reference language"
|
||||
} else {
|
||||
$gTrRefTextField state !disabled
|
||||
}
|
||||
}
|
||||
$gTrLangSelect selection clear
|
||||
$gTrRefLangSelect selection clear
|
||||
}
|
||||
|
||||
proc gTrLoadTranslations {} {
|
||||
global translationLangs gTrLangSelect gTrLangValue gTrRefLangSelect gTrRefLangValue
|
||||
set prevLang $gTrLangValue
|
||||
set prevRefLang $gTrRefLangValue
|
||||
$gTrLangSelect configure -values $translationLangs
|
||||
$gTrRefLangSelect configure -values [linsert $translationLangs 0 ""]
|
||||
if {[llength $translationLangs] < 1} {
|
||||
tk_messageBox -icon error type ok -title "Error" -message "No translation files present."
|
||||
exit 1
|
||||
}
|
||||
if {$prevLang ni $translationLangs} {
|
||||
$gTrLangSelect current 0
|
||||
}
|
||||
if {$prevRefLang ni $translationLangs} {
|
||||
$gTrRefLangSelect current 0
|
||||
}
|
||||
gTrLoadTranslationsToTreeview
|
||||
}
|
||||
|
||||
proc gTrApplyTranslationString args {
|
||||
global gTrTreeview gTrLangValue gTrOrigTextValue gTrTranslatedTextValue
|
||||
set focused [$gTrTreeview focus]
|
||||
if {![$gTrTreeview tag has notranslate $focused]} {
|
||||
setTranslationString $gTrLangValue $gTrOrigTextValue $gTrTranslatedTextValue
|
||||
$gTrTreeview item $focused -values [list $gTrTranslatedTextValue]
|
||||
}
|
||||
}
|
||||
|
||||
# Translation Template Editor
|
||||
|
||||
gAddTab tm "Template" \
|
||||
[list addStringMenuBtn addHeadingMenuBtn removeMenuBtn moveMenuBtn textField setMenuBtn treeviewFrame] \
|
||||
[list textValue]
|
||||
set gTmTreeview "$gTmTreeviewFrame.main"
|
||||
set gTmTreeviewScrollbar "$gTmTreeviewFrame.scrollbar"
|
||||
|
||||
set gTmRowCount 0
|
||||
foreach i [list \
|
||||
[gAddMenu gTmAddStringMenu [ttk::menubutton $gTmAddStringMenuBtn -text "Add string"] "menu" [list \
|
||||
[list command -label "Insert before current entry" -command {gTmInsertStringAt true 0}] \
|
||||
[list command -label "Insert after current entry" -command {gTmInsertStringAt true 1}] \
|
||||
[list command -label "Insert as the first entry" -command {gTmInsertStringAt false 0}] \
|
||||
[list command -label "Insert as the last entry" -command {gTmInsertStringAt false end}] \
|
||||
]] \
|
||||
[gAddMenu gTmAddHeadingMenu [ttk::menubutton $gTmAddHeadingMenuBtn -text "Add heading"] "menu" [list \
|
||||
[list command -label "Insert before current section" -command {gTmInsertHeadingAt true 0}] \
|
||||
[list command -label "Insert after current section" -command {gTmInsertHeadingAt true 1}] \
|
||||
]] \
|
||||
[gAddMenu gTmRemoveMenu [ttk::menubutton $gTmRemoveMenuBtn -text "Remove"] "menu" [list \
|
||||
[list command -label "Remove entry" -command gTmDeleteEntry] \
|
||||
[list command -label "Remove section" -command gTmDeleteEntry] \
|
||||
[list command -label "Merge with previous section" -command gTmMergeWithPrevious] \
|
||||
]] \
|
||||
[gAddMenu gTmMoveMenu [ttk::menubutton $gTmMoveMenuBtn -text "Move"] "menu" [list \
|
||||
[list command -label "Up" -command {gTmMoveInSection true -1}] \
|
||||
[list command -label "Down" -command {gTmMoveInSection true 1}] \
|
||||
[list command -label "To first" -command {gTmMoveInSection false 0}] \
|
||||
[list command -label "To last" -command {gTmMoveInSection false end}] \
|
||||
]] \
|
||||
] {
|
||||
grid $i -column 1 -row $gTmRowCount -sticky we
|
||||
incr gTmRowCount
|
||||
}
|
||||
|
||||
ttk::frame $gTmTreeviewFrame -borderwidth 1 -relief sunken
|
||||
grid $gTmTreeviewFrame -column 0 -row 0 -rowspan [expr {1+$gTmRowCount}] -sticky nsew
|
||||
grid rowconfigure $gTmTreeviewFrame 0 -weight 1
|
||||
grid columnconfigure $gTmTreeviewFrame 0 -weight 1
|
||||
grid rowconfigure $gTmFrame $gTmRowCount -weight 1
|
||||
grid columnconfigure $gTmFrame 0 -weight 1
|
||||
ttk::treeview $gTmTreeview -selectmode browse -show tree -yscrollcommand {$gTmTreeviewScrollbar set}
|
||||
bind $gTmTreeview <<TreeviewSelect>> gTmTreeviewSelectionCallback
|
||||
grid $gTmTreeview -column 0 -row 0 -sticky nsew
|
||||
ttk::scrollbar $gTmTreeviewScrollbar -orient vertical -command {$gTmTreeview yview}
|
||||
grid $gTmTreeviewScrollbar -column 1 -row 0 -sticky ns
|
||||
incr gTmRowCount
|
||||
|
||||
ttk::entry $gTmTextField -textvariable gTmTextValue
|
||||
grid $gTmTextField -column 0 -row $gTmRowCount -sticky nsew
|
||||
|
||||
gAddMenu gTmSetMenu [ttk::menubutton $gTmSetMenuBtn -text "Set"] "menu" [list \
|
||||
[list command -label "Set heading" -command gTmSetEntry] \
|
||||
[list command -label "Set and copy translations" -command gTmSetEntryAndCopy] \
|
||||
[list command -label "Set without copying translations" -command gTmSetEntry] \
|
||||
]
|
||||
grid $gTmSetMenuBtn -column 1 -row $gTmRowCount -sticky nsew
|
||||
|
||||
proc gTmLoadTranslationsToTreeview {} {
|
||||
global translationTemplate gTmTreeview
|
||||
set prevFocus [$gTmTreeview item [$gTmTreeview focus] -text]
|
||||
array set openedSections [list]
|
||||
foreach i [$gTmTreeview children {}] {
|
||||
if {[$gTmTreeview item $i -open]} {
|
||||
set openedSections([$gTmTreeview item $i -text]) 1
|
||||
}
|
||||
}
|
||||
$gTmTreeview delete [$gTmTreeview children {}]
|
||||
set parent {}
|
||||
foreach i [lrange $translationTemplate 1 end] {
|
||||
if {[regexp {^\#+\s*(.+)} $i x comment]} {
|
||||
set parent [$gTmTreeview insert {} end -text $comment -tags {heading}]
|
||||
if {[info exists openedSections($comment)]} {
|
||||
$gTmTreeview item $parent -open true
|
||||
}
|
||||
if {$comment eq $prevFocus} {
|
||||
$gTmTreeview focus $parent
|
||||
$gTmTreeview selection set $parent
|
||||
}
|
||||
} elseif {$i ne ""} {
|
||||
set last [$gTmTreeview insert $parent end -text $i]
|
||||
if {$i eq $prevFocus} {
|
||||
$gTmTreeview focus $last
|
||||
$gTmTreeview selection set $last
|
||||
}
|
||||
}
|
||||
}
|
||||
gTmTreeviewSelectionCallback
|
||||
}
|
||||
|
||||
proc gTmTreeviewSelectionCallback {} {
|
||||
global gTmTreeview gTmTextField gTmTextValue gTmAddStringMenu gTmAddHeadingMenu gTmRemoveMenu gTmMoveMenu gTmSetMenu
|
||||
set focused [$gTmTreeview focus]
|
||||
if {$focused eq {}} {
|
||||
$gTmTextField state disabled
|
||||
set gTmTextValue "Select an entry to edit"
|
||||
foreach m [list $gTmAddStringMenu $gTmAddHeadingMenu $gTmRemoveMenu $gTmMoveMenu $gTmSetMenu] {
|
||||
for {set i 0} {$i <= [$m index end]} {incr i} { $m entryconfigure $i -state disabled}
|
||||
}
|
||||
} else {
|
||||
$gTmTextField state !disabled
|
||||
set headingSetState disabled
|
||||
set entrySetState normal
|
||||
if {[$gTmTreeview tag has heading $focused]} {
|
||||
set headingSetState normal
|
||||
set entrySetState disabled
|
||||
}
|
||||
foreach ent [list \
|
||||
[list $gTmAddStringMenu \
|
||||
[list 0 -state $entrySetState] \
|
||||
[list 1 -state $entrySetState] \
|
||||
[list 2 -state normal] \
|
||||
[list 3 -state normal] \
|
||||
] \
|
||||
[list $gTmAddHeadingMenu \
|
||||
[list 0 -state normal] \
|
||||
[list 1 -state normal] \
|
||||
] \
|
||||
[list $gTmMoveMenu \
|
||||
[list 0 -state normal] \
|
||||
[list 1 -state normal] \
|
||||
[list 2 -state normal] \
|
||||
[list 3 -state normal] \
|
||||
] \
|
||||
[list $gTmRemoveMenu \
|
||||
[list 0 -state $entrySetState] \
|
||||
[list 1 -state $headingSetState] \
|
||||
[list 2 -state $headingSetState] \
|
||||
] \
|
||||
[list $gTmSetMenu \
|
||||
[list 0 -state $headingSetState] \
|
||||
[list 1 -state $entrySetState] \
|
||||
[list 2 -state $entrySetState] \
|
||||
] \
|
||||
] {
|
||||
set m [lindex $ent 0]
|
||||
lmap i [lrange $ent 1 end] {
|
||||
$m entryconfigure {*}$i
|
||||
}
|
||||
}
|
||||
set gTmTextValue [$gTmTreeview item $focused -text]
|
||||
}
|
||||
}
|
||||
|
||||
proc gTmUpdateTemplateAux {parent} {
|
||||
global translationTemplate gTmTreeview
|
||||
foreach i [$gTmTreeview children $parent] {
|
||||
set tval [$gTmTreeview item $i -text]
|
||||
if {[$gTmTreeview tag has heading $i]} {
|
||||
lappend translationTemplate {}
|
||||
set tval "# $tval"
|
||||
}
|
||||
lappend translationTemplate $tval
|
||||
gTmUpdateTemplateAux $i
|
||||
}
|
||||
}
|
||||
|
||||
proc gTmUpdateTemplate {} {
|
||||
global translationTemplate translationDomain
|
||||
set translationTemplate [list "# textdomain: $translationDomain"]
|
||||
gTmUpdateTemplateAux {}
|
||||
gTrLoadTranslations
|
||||
gTmLoadTranslationsToTreeview
|
||||
}
|
||||
|
||||
proc gTmSetEntry {} {
|
||||
global gTmTreeview gTmTextValue
|
||||
$gTmTreeview item [$gTmTreeview focus] -text $gTmTextValue
|
||||
gTmUpdateTemplate
|
||||
}
|
||||
|
||||
proc gTmSetEntryAndCopy {} {
|
||||
global gTmTreeview gTmTextValue
|
||||
set focus [$gTmTreeview focus]
|
||||
rewordTranslationString [$gTmTreeview item $focus -text] $gTmTextValue
|
||||
gTmSetEntry
|
||||
}
|
||||
|
||||
proc gTmInsertStringAt {relative idx} {
|
||||
global gTmTreeview
|
||||
set focus [$gTmTreeview focus]
|
||||
set parent [$gTmTreeview parent $focus]
|
||||
set relidx [$gTmTreeview index $focus]
|
||||
if {[$gTmTreeview tag has heading $focus]} {
|
||||
set parent $focus
|
||||
set relindex 0
|
||||
}
|
||||
set newidx $idx
|
||||
if {$relative} {
|
||||
set newidx [expr {$idx+$relidx}]
|
||||
}
|
||||
set item [$gTmTreeview insert $parent $newidx -text {}]
|
||||
$gTmTreeview focus $item
|
||||
$gTmTreeview selection set $item
|
||||
}
|
||||
|
||||
proc gTmInsertHeadingAt {relative idx} {
|
||||
global gTmTreeview
|
||||
set focus [$gTmTreeview focus]
|
||||
if {![$gTmTreeview tag has heading $focus]} {
|
||||
set focus [$gTmTreeview parent $focus]
|
||||
}
|
||||
set parent [$gTmTreeview parent $focus]
|
||||
set relidx [$gTmTreeview index $focus]
|
||||
if {$focus eq {}} {
|
||||
set parent {}
|
||||
set relidx 0
|
||||
}
|
||||
set newidx $idx
|
||||
if {$relative} {
|
||||
set newidx [expr {$idx+$relidx}]
|
||||
}
|
||||
set item [$gTmTreeview insert $parent $newidx -text {} -tags {heading}]
|
||||
$gTmTreeview focus $item
|
||||
$gTmTreeview selection set $item
|
||||
}
|
||||
|
||||
proc gTmMoveInSection {relative idx} {
|
||||
global gTmTreeview
|
||||
set focus [$gTmTreeview focus]
|
||||
set parent [$gTmTreeview parent $focus]
|
||||
set relidx [$gTmTreeview index $focus]
|
||||
set newidx $idx
|
||||
if {$relative} {
|
||||
set newidx [expr {$idx+$relidx}]
|
||||
}
|
||||
$gTmTreeview move $focus $parent $newidx
|
||||
gTmUpdateTemplate
|
||||
}
|
||||
|
||||
proc gTmDeleteEntry {} {
|
||||
global gTmTreeview
|
||||
$gTmTreeview delete [$gTmTreeview focus]
|
||||
gTmUpdateTemplate
|
||||
}
|
||||
|
||||
proc gTmMergeWithPrevious {} {
|
||||
global gTmTreeview
|
||||
set parent [$gTmTreeview focus]
|
||||
set prev [$gTmTreeview prev $parent]
|
||||
set newindex end
|
||||
if {$prev eq {}} {
|
||||
set prev [$gTmTreeview parent $parent]
|
||||
set newindex 0
|
||||
}
|
||||
foreach i [$gTmTreeview children $parent] {
|
||||
$gTmTreeview move $i $prev $newindex
|
||||
}
|
||||
$gTmTreeview delete $parent
|
||||
gTmUpdateTemplate
|
||||
}
|
||||
|
||||
proc gTmLoadTranslations {} {
|
||||
gTmLoadTranslationsToTreeview
|
||||
}
|
||||
|
||||
# Initialization
|
||||
|
||||
gReloadTranslations
|
|
@ -1,146 +0,0 @@
|
|||
# textdomain: advtrains
|
||||
|
||||
# Advtrains Core (unorganized)
|
||||
This wagon is owned by @1, you can't destroy it.=This wagon is owned by @1, you can't destroy it.
|
||||
Warning: If you destroy this wagon, you only get some steel back! If you are sure, hold Sneak and left-click the wagon.=Warning: If you destroy this wagon, you only get some steel back! If you are sure, hold Sneak and left-click the wagon.
|
||||
This position is protected!=This position is protected!
|
||||
Can't place: not pointing at node=Can't place: not pointing at node
|
||||
Can't place: space occupied!=Can't place: space occupied!
|
||||
Can't place: protected position!=Can't place: protected position!
|
||||
Can't place: Not enough slope items left (@1 required)=Can't place: Not enough slope items left (@1 required)
|
||||
Can't place: There's no slope of length @1=Can't place: There's no slope of length @1
|
||||
Can't place: no supporting node at upper end.=Can't place: no supporting node at upper end.
|
||||
Deprecated Track=Deprecated Track
|
||||
Can't get on: wagon full or doors closed!=Can't get on: wagon full or doors closed!
|
||||
Use Sneak+rightclick to bypass closed doors!=Use Sneak+rightclick to bypass closed doors!
|
||||
Doors are closed! Use Sneak+rightclick to ignore the closed doors and get off!=Doors are closed! Use Sneak+rightclick to ignore the closed doors and get off!
|
||||
Access to @1=Access to @1
|
||||
You do not have the @1 privilege.=You do not have the @1 privilege.
|
||||
The wagon's inventory is not empty!=The wagon's inventory is not empty!
|
||||
Position is occupied by a train.=Position is occupied by a train.
|
||||
There's a Track Circuit Break here.=There's a Track Circuit Break here.
|
||||
There's a Signal Influence Point here.=There's a Signal Influence Point here.
|
||||
|
||||
# Trackworker, rotation, adjustment
|
||||
This node can't be rotated using the trackworker!=This node can't be rotated using the trackworker!
|
||||
This node can't be changed using the trackworker!=This node can't be changed using the trackworker!
|
||||
This track can not be changed!=This track can not be changed!
|
||||
This track can not be rotated!=This track can not be rotated!
|
||||
This track can not be removed!=This track can not be removed!
|
||||
|
||||
# ATC
|
||||
ATC controller, unconfigured.=ATC controller, unconfigured.
|
||||
ATC controller=ATC controller
|
||||
ATC controller, mode @1@nChannel: @2=ATC controller, mode @1@nChannel: @2
|
||||
ATC controller, mode @1@nCommand: @2=ATC controller, mode @1@nCommand: @2
|
||||
Command=Command
|
||||
Command (on)=Command (on)
|
||||
Digiline channel=Digiline channel
|
||||
ATC Kick command warning: Doors closed=ATC Kick command warning: Doors closed
|
||||
ATC Kick command warning: Train moving=ATC Kick command warning: Train moving
|
||||
ATC Reverse command warning: didn't reverse train, train moving!=ATC Reverse command warning: didn't reverse train, train moving!
|
||||
ATC command syntax error: I statement not closed: @1=ATC command syntax error: I statement not closed: @1
|
||||
ATC command parse error: Unknown command: @1=ATC command parse error: Unknown command: @1
|
||||
|
||||
# Coupling
|
||||
Lock couples=Lock couples
|
||||
You need to own at least one neighboring wagon to destroy this couple.=You need to own at least one neighboring wagon to destroy this couple.
|
||||
Buffer and Chain Coupler=Buffer and Chain Coupler
|
||||
Scharfenberg Coupler=Scharfenberg Coupler
|
||||
Japanese Train Inter-Wagon Connection=Japanese Train Inter-Wagon Connection
|
||||
Can not couple: The couplers of the trains do not match (@1 and @2).=Can not couple: The couplers of the trains do not match (@1 and @2).
|
||||
You are not allowed to couple trains without the train_operator privilege.=You are not allowed to couple trains without the train_operator privilege.
|
||||
|
||||
# Clipboard
|
||||
The track you are trying to place the wagon on is not long enough!=The track you are trying to place the wagon on is not long enough!
|
||||
The clipboard couldn't access the metadata. Paste failed.=The clipboard couldn't access the metadata. Paste failed.
|
||||
The clipboard couldn't access the metadata. Copy failed.=The clipboard couldn't access the metadata. Copy failed.
|
||||
The clipboard is empty.=The clipboard is empty.
|
||||
Back of train would end up off track, cancelling.=Back of train would end up off track, cancelling.
|
||||
No such lua entity!=No such lua entity!
|
||||
No such wagon: @1=No such wagon: @1
|
||||
No such train: @1=No such train: @1
|
||||
Train copied!=Train copied!
|
||||
|
||||
# Protection
|
||||
You are not allowed to build tracks without the track_builder privilege.=You are not allowed to build tracks without the track_builder privilege.
|
||||
You are not allowed to build near tracks without the track_builder privilege.=You are not allowed to build near tracks without the track_builder privilege.
|
||||
You are not allowed to build tracks at this protected position.=You are not allowed to build tracks at this protected position.
|
||||
You are not allowed to build near tracks at this protected position.=You are not allowed to build near tracks at this protected position.
|
||||
You are not allowed to operate turnouts and signals without the railway_operator privilege.=You are not allowed to operate turnouts and signals without the railway_operator privilege.
|
||||
|
||||
# Train HUD/Formspecs
|
||||
Speed:=Speed:
|
||||
Target:=Target:
|
||||
Show Inventory=Show Inventory
|
||||
Select seat:=Select seat:
|
||||
Wagon properties=Wagon properties
|
||||
Save wagon properties=Save wagon properties
|
||||
Text displayed outside on train=Text displayed outside on train
|
||||
Text displayed inside train=Text displayed inside train
|
||||
Line=Line
|
||||
Routingcode=Routingcode
|
||||
Get off=Get off
|
||||
Get off (forced)=Get off (forced)
|
||||
(Doors closed)=(Doors closed)
|
||||
|
||||
# General
|
||||
Save=Save
|
||||
|
||||
# Line automation
|
||||
Station Code=Station Code
|
||||
Station Name=Station Name
|
||||
Door Delay=Door Delay
|
||||
Door Side=Door Side
|
||||
Dep. Speed=Dep. Speed
|
||||
Stop Time=Stop Time
|
||||
|
||||
# Items
|
||||
Track Worker Tool@n@nLeft-click: change rail type (straight/curve/switch)@nRight-click: rotate rail/bumper/signal/etc.=Track Worker Tool@n@nLeft-click: change rail type (straight/curve/switch)@nRight-click: rotate rail/bumper/signal/etc.
|
||||
Passive Component Naming Tool@n@nRight-click to name a passive component.=Passive Component Naming Tool@n@nRight-click to name a passive component.
|
||||
Train copy/paste tool@n@nLeft-click: copy train@nRight-click: paste train=Train copy/paste tool@n@nLeft-click: copy train@nRight-click: paste train
|
||||
Track=Track
|
||||
Perpendicular Diamond Crossing Track=Perpendicular Diamond Crossing Track
|
||||
Diagonal Diamond Crossing Track=Diagonal Diamond Crossing Track
|
||||
90+Angle Diamond Crossing Track=90+Angle Diamond Crossing Track
|
||||
Y-turnout=Y-turnout
|
||||
3-way turnout=3-way turnout
|
||||
Unloading Track=Unloading Track
|
||||
Loading Track=Loading Track
|
||||
Bumper=Bumper
|
||||
Detector Rail=Detector Rail
|
||||
@1 Slope=@1 Slope
|
||||
@1 Platform (low)=@1 Platform (low)
|
||||
@1 Platform (high)=@1 Platform (high)
|
||||
@1 Platform (low, 45 degree)=@1 Platform (low, 45 degree)
|
||||
@1 Platform (45 degree)=@1 Platform (45 degree)
|
||||
Lampless Signal=Lampless Signal
|
||||
Signal=Signal
|
||||
Wallmounted Signal (l)=Wallmounted Signal (l)
|
||||
Wallmounted Signal (r)=Wallmounted Signal (r)
|
||||
Wallmounted Signal (t)=Wallmounted Signal (t)
|
||||
Andrew's Cross=Andrew's Cross
|
||||
Boiler=Boiler
|
||||
driver's cab=driver's cab
|
||||
Wheel=Wheel
|
||||
Chimney=Chimney
|
||||
|
||||
# Seats
|
||||
Default Seat=Default Seat
|
||||
Default Seat (driver stand)=Default Seat (driver stand)
|
||||
Driver stand=Driver stand
|
||||
Driver Stand (left)=Driver Stand (left)
|
||||
Driver Stand (right)=Driver Stand (right)
|
||||
|
||||
# Wagon/engine types
|
||||
Industrial Train Engine=Industrial Train Engine
|
||||
Big Industrial Train Engine=Big Industrial Train Engine
|
||||
Industrial tank wagon=Industrial tank wagon
|
||||
Industrial wood wagon=Industrial wood wagon
|
||||
Japanese Train Engine=Japanese Train Engine
|
||||
Japanese Train Wagon=Japanese Train Wagon
|
||||
Steam Engine=Steam Engine
|
||||
Detailed Steam Engine=Detailed Steam Engine
|
||||
Passenger Wagon=Passenger Wagon
|
||||
Box Wagon=Box Wagon
|
||||
Subway Passenger Wagon=Subway Passenger Wagon
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
head -n18 ../po/template.pot | sed 's/charset=CHARSET/charset=UTF-8/'
|
||||
sed -En 's/@n/\\n/g;s/@\n/\\n/g;s/\"/\\"/g;s/^([^=]+)=\1$/\1=/;s/^([^=]+)=([^=]*)$/\nmsgid "\1"\nmsgstr "\2"/gp'
|
|
@ -0,0 +1,70 @@
|
|||
# Translations
|
||||
Please read this document before working on any translations.
|
||||
|
||||
Unlike many other mods, Advtrains uses `.po` files for localization,
|
||||
which are then automatically converted to `.tr` files when the mod is
|
||||
loaded. Therefore, please submit patches that edit the `.po` files.
|
||||
|
||||
## Getting Started
|
||||
The translation files can be edited like any other `.po` file.
|
||||
|
||||
If the translation file for your language does not exist, create it by
|
||||
copying `template.txt` to `advtrains.XX.tr`, where `XX` is replaced by
|
||||
the language code.
|
||||
|
||||
Feel free to use the [discussion mailing list][srht-discuss] if you
|
||||
have any questions regarding localization.
|
||||
|
||||
You can share your `.po` file directly or [as a patch][gsm] to the [dev
|
||||
mailing list][srht-devel]. The latter is encouraged, but, unlike code
|
||||
changes, translation files sent directly are also accepted.
|
||||
|
||||
[tr-format]: https://minetest.gitlab.io/minetest/translations/#translation-file-format
|
||||
[srht-discuss]: https://lists.sr.ht/~gpcf/advtrains-discuss
|
||||
[srht-devel]: https://lists.sr.ht/~gpcf/advtrains-devel
|
||||
[gsm]: https://git-send-email.io
|
||||
|
||||
## Translation Notes
|
||||
* Translations should be consistent. You can use other entries or the
|
||||
translations in Minetest as a reference.
|
||||
* Translations do not have to fully correspond to the original text -
|
||||
they only need to provide the same information. In particular,
|
||||
translations do not need to have the same linguistical structure as the
|
||||
original text.
|
||||
* Replacement sequences (`@1`, `@2`, etc) should not be translated.
|
||||
* Certain abbreviations or names, such as "Ks" or "Zs 3", should
|
||||
generally not be translated.
|
||||
|
||||
### (de) German
|
||||
* Verwenden Sie die neue Rechtschreibung und die Sie-Form.
|
||||
* Mit der deutschen Tastaturbelegung unter Linux können die
|
||||
Anführungszeichen „“ mit AltGr-V bzw. AltGr-B eingegeben werden.
|
||||
|
||||
### (zh) Chinese
|
||||
(This section is written in English to avoid writing the note twice or
|
||||
using only one of the variants, as most of this section applies to both
|
||||
the traditional and simplified variants.)
|
||||
|
||||
* Please use the 「」 quotation marks for Traditional Chinese and “”
|
||||
for Simplified Chinese.
|
||||
* Please use the fullwidth variants of: , 、 。 ? ! : ;
|
||||
* Please use the halfwidth variants of: ( ) [ ] / \ |
|
||||
* Please do not leave any space between Han characters (including
|
||||
fullwidth punctuation marks).
|
||||
* Please leave a space between Han characters (excluding fullwidth
|
||||
punctuation marks) and characters from other scripts (including
|
||||
halfwidth punctuation marks). However, do not leave any space between
|
||||
Han characters and Arabic numerals.
|
||||
|
||||
## Notes for developers
|
||||
* The `update-translations.sh` script can be used to update the
|
||||
translation files. However, please make sure to install the
|
||||
`basic_trains` mod before running the script.
|
||||
* Please make sure that the first argument to `S` (or `attrans`) _only_
|
||||
includes string literals without formatting or concatenation. This is
|
||||
unfortunately a limitation of the `xgettext` utility.
|
||||
* Avoid word-by-word translations.
|
||||
* Avoid manipulating translated strings (except for concatenation). Use
|
||||
server-side translations if you have to modify the text sent to users.
|
||||
* Avoid truncating strings unless multibyte characters are handled
|
||||
properly.
|
|
@ -0,0 +1,185 @@
|
|||
local unescape_string
|
||||
do
|
||||
local schartbl = { -- https://en.wikipedia.org/wiki/Escape_sequences_in_C
|
||||
a = "\a",
|
||||
b = "\b",
|
||||
e = string.char(0x1b),
|
||||
f = "\f",
|
||||
n = "\n",
|
||||
r = "\r",
|
||||
t = "\t",
|
||||
v = "\v",
|
||||
}
|
||||
local function replace_single(pfx, c)
|
||||
local pl = #pfx
|
||||
if pl % 2 == 0 then
|
||||
return string.sub(pfx, 1, pl/2) .. c
|
||||
end
|
||||
return string.sub(pfx, 1, math.floor(pl/2)) .. (schartbl[c] or c)
|
||||
end
|
||||
unescape_string = function(str)
|
||||
return string.gsub(str, [[(\+)([abefnrtv'"?])]], replace_single)
|
||||
end
|
||||
end
|
||||
|
||||
local function readstring_aux(str, pos)
|
||||
local _, spos = string.find(str, [[^%s*"]], pos)
|
||||
if not spos then
|
||||
return nil
|
||||
end
|
||||
local ipos = spos
|
||||
while true do
|
||||
local _, epos, m = string.find(str, [[(\*)"]], ipos+1)
|
||||
if not epos then
|
||||
return error("String extends beyond the end of input")
|
||||
end
|
||||
ipos = epos
|
||||
if #m % 2 == 0 then
|
||||
return unescape_string(string.sub(str, spos+1, epos-1)), epos+1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function readstring(str, pos)
|
||||
local st = {}
|
||||
local nxt = pos
|
||||
while true do
|
||||
local s, npos = readstring_aux(str, nxt)
|
||||
if not s then
|
||||
if not st[1] then
|
||||
return nil, nxt
|
||||
else
|
||||
return table.concat(st), nxt
|
||||
end
|
||||
end
|
||||
nxt = npos
|
||||
table.insert(st, s)
|
||||
end
|
||||
end
|
||||
|
||||
local function readtoken(str, pos)
|
||||
local _, epos, tok = string.find(str, [[^%s*(%S+)]], pos)
|
||||
if epos == nil then
|
||||
return nil, pos
|
||||
end
|
||||
return tok, epos+1
|
||||
end
|
||||
|
||||
local function readcomment_add_flags(flags, s)
|
||||
for flag in string.gmatch(s, ",%s*([^,]+)") do
|
||||
flags[flag] = true
|
||||
end
|
||||
end
|
||||
|
||||
local function readcomment_aux(str, pos)
|
||||
local _, epos, sval = string.find(str, "^\n*#([^\n]*)", pos)
|
||||
if not epos then
|
||||
return nil
|
||||
end
|
||||
return sval, epos+1
|
||||
end
|
||||
|
||||
local function readcomment(str, pos)
|
||||
local st = {}
|
||||
local nxt = pos
|
||||
local flags = {}
|
||||
while true do
|
||||
local s, npos = readcomment_aux(str, nxt)
|
||||
if not npos then
|
||||
local t = {
|
||||
comment = table.concat(st, "\n"),
|
||||
flags = flags,
|
||||
}
|
||||
return t, nxt
|
||||
end
|
||||
if string.sub(s, 1, 1) == "," then
|
||||
readcomment_add_flags(flags, s)
|
||||
end
|
||||
table.insert(st, s)
|
||||
nxt = npos
|
||||
end
|
||||
end
|
||||
|
||||
local function readpo(str)
|
||||
local st = {}
|
||||
local pos = 1
|
||||
while true do
|
||||
local entry, nxt = readcomment(str, pos)
|
||||
local msglines = 0
|
||||
while true do
|
||||
local tok, npos = readtoken(str, nxt)
|
||||
if tok == nil or string.sub(tok, 1, 1) == "#" then
|
||||
break
|
||||
elseif string.sub(tok, 1, 3) ~= "msg" then
|
||||
return error("Invalid token: " .. tok)
|
||||
elseif entry[tok] ~= nil then
|
||||
break
|
||||
else
|
||||
local value, npos = readstring(str, npos)
|
||||
assert(value ~= nil, "No string provided for " .. tok)
|
||||
entry[tok] = value
|
||||
nxt = npos
|
||||
msglines = msglines+1
|
||||
end
|
||||
end
|
||||
if msglines == 0 then
|
||||
return st
|
||||
elseif entry.msgid ~= "" then
|
||||
assert(entry.msgid ~= nil, "Missing untranslated string")
|
||||
assert(entry.msgstr ~= nil, "Missing translated string")
|
||||
table.insert(st, entry)
|
||||
end
|
||||
pos = nxt
|
||||
end
|
||||
end
|
||||
|
||||
local escape_lookup = {
|
||||
["="] = "@=",
|
||||
["\n"] = "@n"
|
||||
}
|
||||
local function escape_string(st)
|
||||
return (string.gsub(st, "[=\n]", escape_lookup))
|
||||
end
|
||||
|
||||
local function convert_po_string(textdomain, str)
|
||||
local st = {string.format("# textdomain: %s", textdomain)}
|
||||
for _, entry in ipairs(readpo(str)) do
|
||||
local line = ("%s=%s"):format(escape_string(entry.msgid), escape_string(entry.msgstr))
|
||||
if entry.flags.fuzzy then
|
||||
line = "#" .. line
|
||||
end
|
||||
table.insert(st, line)
|
||||
end
|
||||
return table.concat(st, "\n")
|
||||
end
|
||||
|
||||
local function convert_po_file(textdomain, inpath, outpath)
|
||||
local f, err = io.open(inpath, "rb")
|
||||
assert(f, err)
|
||||
local str = convert_po_string(textdomain, f:read("*a"))
|
||||
f:close()
|
||||
minetest.safe_file_write(outpath, str)
|
||||
return str
|
||||
end
|
||||
|
||||
local function convert_flat_po_directory(textdomain, modpath)
|
||||
assert(textdomain, "No textdomain specified for po file conversion")
|
||||
local mp = modpath or minetest.get_modpath(textdomain)
|
||||
assert(mp ~= nil, "No path to write for " .. textdomain)
|
||||
local popath = mp .. "/po"
|
||||
local trpath = mp .. "/locale"
|
||||
for _, infile in pairs(minetest.get_dir_list(popath, false)) do
|
||||
local lang = string.match(infile, [[^([^%.]+)%.po$]])
|
||||
if lang then
|
||||
local inpath = popath .. "/" .. infile
|
||||
local outpath = ("%s/%s.%s.tr"):format(trpath, textdomain, lang)
|
||||
convert_po_file(textdomain, inpath, outpath)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
from_string = convert_po_string,
|
||||
from_file = convert_po_file,
|
||||
from_flat = convert_flat_po_directory,
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package.path = "../?.lua;" .. package.path
|
||||
advtrains = {}
|
||||
_G.advtrains = advtrains
|
||||
local poconvert = require("poconvert")
|
||||
|
||||
describe("PO file converter", function()
|
||||
it("should convert PO files", function()
|
||||
assert.equals([[
|
||||
# textdomain: foo
|
||||
foo=bar
|
||||
baz=
|
||||
#@=wh\at\\@n=@=w\as\\@n
|
||||
multiline@nstrings=multiline@nresult
|
||||
with context?=oder doch nicht]], poconvert.from_string("foo", [[
|
||||
msgid ""
|
||||
msgstr "whatever metadata"
|
||||
|
||||
msgid "foo"
|
||||
msgstr "bar"
|
||||
|
||||
msgid "baz"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "=wh\\at\\\\\n"
|
||||
msgstr "=w\\as\\\\\n"
|
||||
|
||||
msgid "multi"
|
||||
"line\n"
|
||||
"strings"
|
||||
msgstr "multi"
|
||||
"line\n"
|
||||
"result"
|
||||
|
||||
msgctxt "i18n context"
|
||||
msgid "with context?"
|
||||
msgstr "oder doch nicht"]]))
|
||||
end)
|
||||
it("should reject invalid tokens", function()
|
||||
assert.has.errors(function()
|
||||
poconvert.from_string("", [[
|
||||
foo ""
|
||||
bar ""]])
|
||||
end, "Invalid token: foo")
|
||||
end)
|
||||
it("should reject entries without a msgstr", function()
|
||||
assert.has.errors(function()
|
||||
poconvert.from_string("", [[msgid "foo"]])
|
||||
end, "Missing translated string")
|
||||
end)
|
||||
it("should reject entries without a msgid", function()
|
||||
assert.has.errors(function()
|
||||
poconvert.from_string("", [[msgstr "foo"]])
|
||||
end, "Missing untranslated string")
|
||||
end)
|
||||
it("should reject entries with improperly enclosed strings", function()
|
||||
assert.has.errors(function()
|
||||
poconvert.from_string("", [[
|
||||
msgid "foo"
|
||||
msgstr "bar \]])
|
||||
end, "String extends beyond the end of input")
|
||||
end)
|
||||
it("should reject incomplete input", function()
|
||||
assert.has.errors(function()
|
||||
poconvert.from_string("", [[
|
||||
msgid "foo"
|
||||
msgstr]])
|
||||
end, "No string provided for msgstr")
|
||||
end)
|
||||
end)
|
Loading…
Reference in New Issue