Beide kanten vorige revisieVorige revisieVolgende revisie | Vorige revisieVolgende revisieBeide kanten volgende revisie |
nl:howtos:misc:internationalization_and_localization_of_shell_scripts [2014/12/29 01:02 (UTC)] – [Waarschuwing over vertaling van man paginas] Vertaald. alienbob | nl:howtos:misc:internationalization_and_localization_of_shell_scripts [2014/12/29 21:27 (UTC)] – [Procesdiagrammen] kleine aanpassingen. alienbob |
---|
Een berichten sjabloon-catalogus wordt gewoonlijk een "Portable Object Template" of POT bestand genoemd. | Een berichten sjabloon-catalogus wordt gewoonlijk een "Portable Object Template" of POT bestand genoemd. |
| |
Een POT bestand, leesbare platte tekst, bestaat voornamelijk uit de geëxtraheerde tekst-reeksen, vooraf gegaan door "msgid" wat zoveel betekent als "message identifier", waatbij elk weer wordt gevolgd door een vertaling van dat bericht, dat wordt vooraf gegaan door de tekst "msgstr". | Een POT bestand, leesbare platte tekst, bestaat voornamelijk uit de geëxtraheerde tekst-reeksen, vooraf gegaan door "msgid" wat zoveel betekent als "message identifier". Bij elke "msgid" tekst behoort een vertaling van dat bericht, en deze tekst-reeks wordt vooraf gegaan door het woord "msgstr" wat staat voor "message string". |
| |
Het **Localisatie** proces (verkort tot L10N) bestaat uit: | Het **Localisatie** proces (verkort tot L10N) bestaat uit: |
* alle "msgstr" teksten voorzien van vertalingen in ieder PO bestand, | * alle "msgstr" teksten voorzien van vertalingen in ieder PO bestand, |
* deze PO bestanden controleren/verifiëren na de vertaalslag, | * deze PO bestanden controleren/verifiëren na de vertaalslag, |
* ieder PO bestand individueel compileren tot een "Machine Objet" of MO bestand. | * ieder PO bestand individueel compileren tot een "Machine Object" of MO bestand. |
| |
De MO bestanden die bedoeld zijn voor de machine, niet de mens, vandaar de naam, worden traditioneel opgeslagen als: | De MO bestanden die bedoeld zijn voor de machine, niet de mens (vandaar de naam) worden traditioneel opgeslagen als: |
/usr/share/locale/<locale>/LC_MESSAGES/<software naam>.mo | /usr/share/locale/<locale>/LC_MESSAGES/<software naam>.mo |
| |
| |
Tijdens het uitvoeren van het script wordt zo 'gettext' in staat gesteld om het juiste MO bestand te vinden en iedere gemarkeerde bericht-tekst weer te geven in de voorkeurstaal zoals die door de LANG of LANGUAGE omgevings-variabele is bepaald. | Tijdens het uitvoeren van het script wordt zo 'gettext' in staat gesteld om het juiste MO bestand te vinden en iedere gemarkeerde bericht-tekst weer te geven in de voorkeurstaal zoals die door de LANG of LANGUAGE omgevings-variabele is bepaald. |
| |
| |
==== Procesdiagrammen ==== | ==== Procesdiagrammen ==== |
| |
Laten we aannemen dat een bepaalde software bestaat uit een set shell scripts die we willen internationaliseren enlocaliseren. | Laten we aannemen dat een bepaalde software bestaat uit een verzameling shell scripts die we willen internationaliseren en localiseren. |
| |
De onderstaande diagrammen tonen een overzicht van ieder onderdeel van de betrokken processen: internationalisatie, localisatie, gebruik en onderhoud. | De onderstaande diagrammen tonen een overzicht van iedere fase van de betrokken processen: internationalisatie, localisatie, gebruik en onderhoud. |
| |
Deze diagrammen zijn hybride, dwz ze tonen data zowel als acties. | Deze diagrammen zijn hybride, dwz ze tonen data zowel als acties. |
| |
Onder deze acties zijn uitvoering van een aantal programma's uit de ''gettext'' verzameling: | Onder deze acties vallen de uitvoering van een aantal programma's uit de ''gettext'' verzameling: |
* ''gettetxt'': markeert de te internationaliseren tekstreeksen, en toont later de gelocaliseerde berichten tijdens de uitvoering van het script | * ''gettetxt'': markeert de te internationaliseren tekstreeksen, en toont later de gelocaliseerde berichten tijdens de uitvoering van het script |
* ''xgettext'': extraheert de gemarkeerde tekstreeksen uit een verzameling shell scripts om er een //POT// of een //PO// bestand van op te bouwen | * ''xgettext'': extraheert de gemarkeerde tekstreeksen uit een verzameling shell scripts om er een //POT// of een //PO// bestand van op te bouwen |
=== (3) Gebruik === | === (3) Gebruik === |
| |
Veronderstel dat een van de scripts, "myscript.sh" het volgende commando bevat: | Veronderstel dat een van de scripts, "''myscript.sh''" het volgende commando bevat: |
gettext "Good morning" | gettext "Good morning" |
| |
Het onderhoudsproces kan worden gestart door het creëren, wijzigen of verwijderen van een script. | Het onderhoudsproces kan worden gestart door het creëren, wijzigen of verwijderen van een script. |
| |
In onderstaand diagram moet het onderdeel van het proces dat begint met het ''msmerge'' commando herhaald worden voor ieder beschikbaar PO bestand. | In onderstaand diagram moet het onderdeel van het proces dat begint met het '''msmerge''' commando herhaald worden voor ieder beschikbaar PO bestand. |
| |
Het is daarom aan te raden om een actuele lijst bij te houden van alle beschikbare vertalingen in de vorm van PO bestanden. | Het is daarom aan te raden om een actuele lijst bij te houden van alle beschikbare vertalingen in de vorm van PO bestanden. |
==== Internationalisatie proces ==== | ==== Internationalisatie proces ==== |
| |
This chapter is intended for developers and maintainers. | Deze paragraaf is bedoeld voor ontwikkelaars en maintainers. |
| |
The internationalization process comprises following tasks: | Het internationalisatie proces omvat de volgende taken: |
- Prepare scripts for internationalization | - Bereid scripts voor op internationalisatie |
- Mark messages to be localized | - Markeer de tekstberichten die gelocalizeerd moeten worden |
- Use 'xgettext' to produce a template catalog of messages | - Gebruik '''xgettext''' om een sjabloon catalogus van de tekstberichten te produceren |
| |
=== Scripts ter internationalisatie voorbereiden === | === Scripts ter internationalisatie voorbereiden === |
| |
This task is needed for shell scripts that do not yet fulfill requirements for internationalization. | Deze taak is nodig voor shell scripts die nog niet aan de voorwaarden voldoen voor internationalisatie. |
| |
== Technische notitie: Gettext vereisten voor shell scripts. == | == Technische notitie: Gettext vereisten voor shell scripts. == |
| |
The list of requirements below is not complete. | Onderstaande opsomming van vereisten is niet compleet. |
| |
It includes only the main ones that I recommend the developer or maintainer to check, based on my experience. | Het noemt enkel de voornaamste die de ontwikkelaar of maintainer aangeraden worden, gebaseerd op de auteur's eigen ervaringen. |
| |
Gettext replaces at run time text strings output of: | Gettext vervangt tijdens de uitvoering van het script (dwz 'runtime') tekstberichten die bijvoorbeeld worden uitgestuurd door: |
* an "echo" command or | * Een "echo" commando of |
* a program (like 'dialog', for instance) | * een programma (zoals '''dialog''' bijvoorbeeld) |
with translated text strings (found in a messages catalog for the language set by $LANG or $LANGUAGE) | met vertaalde tekst (die gevonden wordt in de berichten catalogus voor de taal die middels $LANG of $LANGUAGE ingesteld is) |
| |
But the replacement only occurs if following conditions are fulfilled: | Maar deze vervanging vindt alleen plaats wanneer aan de volgende voorwaarden voldaan is: |
* A MO file is available in the path computed from the TEXTDOMAIN environment variable as <dir_name>/<locale>/LC_MESSAGES/text_domain.mo.\\ For instance, if TEXTDOMAIN=software and $LANG=de_DE.utf8, gettext will look for: <dir_name>/de_DE/LC_MESSAGES/software.mo\\ <dir_name> can be set through the value of the TEXTDOMAINDIR environment variable, otherwise a default value is used.\\ In Slackware Linux for instance, the default value is /usr/share/locale.\\ There are fall backs, for instance if <locale> is "de_DE" the mo file could be placed in <dir_name>/de/LC_MESSAGES/ instead of <dir_name>/de_DE/LC_MESSAGES/ | * Een MO bestand is aanwezig in het pad dat samengesteld wordt uit de TEXTDOMAIN omgevingsvariabele tot <directorynaam>/<locale>/LC_MESSAGES/text_domain.mo.\\ Om een voorbeeld te geven, als TEXTDOMAIN=software en $LANG=de_DE.utf8, dan zal ''gettext'' zoeken naar: <directorynaam>/de_DE/LC_MESSAGES/software.mo\\ <directorynaam> kan worden ingesteld door de waarde van de TEXTDOMAINDIR omgevingsvariabele, en anders wordt een standaardwaarde gebruikt.\\ In Slackware Linux bijvoornbeeld is de standaard waarde ''/usr/share/locale''.\\ Er zijn ook alternatieve lokaties: bijvoorbeeld als <locale> gelijk is aan "de_DE" dan kan het MO bestand ook worden geplaatst in <directorynaam>/de/LC_MESSAGES/ in plaats van <directorynaam>/de_DE/LC_MESSAGES/ |
* TEXTDOMAIN variable is exported before any *gettext command occurs. | * TEXTDOMAIN variabele wordt geëxporteerd, voordat enig ''*gettext'' commando wordt uitgevoerd. |
* gettext.sh, which provides the eval_gettext and eval_ngettext functions, is sourced before any occurrence of one of these functions. | * ''gettext.sh'', dat de functies ''eval_gettext'' en ''eval_ngettext'' aanbiedt, wordt ge'//source//'d voor de eerste aanroep van een van deze functies. |
* A msgid string in the MO file matches exactly the argument of gettext (or eval_gettext if the text string includes a parameter expansion). | * Een "msgid" tekstreeks in het MO bestand past exact bij het argument voor ''gettext'' (of ''eval_gettext'' als de tekstreeks een parameter expansie bevat). |
* The corresponding msgstr string does not include a backslash followed by a white space. | * De corresponderende "msgstr" tekstreeks bevat geen backslash die gevolgd wordt door een spatie. |
* The msgstr string begins and ends with a newline or not, as the msgid does. | * De "msgstr" tekstreeks string begint en eindigt met een newline - of niet - precies zoals de "msgid" het doet. |
* If the text string includes a parameter expansion, eval_gettext is used instead of gettext. | * Indien de tekstreeks een parameter expansie bevat, moet ''eval_gettext'' worden gebruikt in plaats van ''gettext''. |
* "The variable names must consist solely of alphanumeric or underscore ASCII characters, not start with a digit and be nonempty; otherwise such a variable reference is ignored." (gettext manual) | * "De variabele namen moeten enkel bestaan uit alfanumerieke of underscore ASCII karakters, niet starten met een cijfer en niet leeg zijn; anders wordt zo een variabele referentie genegeerd." (gettext handleiding) |
* Parameter expansions are escaped with a single backslash like this:\\ \$parameter or \${parameter}\\ unless the eval_gettext command be inside a command substitution like this:\\ "`eval_gettext "..."`" or "$(eval_gettext "...")"\\ In the latter case, three backslashes are needed like this:\\ \\\$parameter or \\\${parameter}. | * Parameter expansies worden escaped met een enkele backslash zoals dit:\\ \$parameter of \${parameter}\\ tenzij de ''eval_gettext'' aanroep zich bevindt binnen een commando substitutie zoals dit:\\ "`eval_gettext "..."`" of "$(eval_gettext "...")"\\ In het laatste geval zijn drie backslashes noodzakelijk zoals dit:\\ \\\$parameter of \\\${parameter}. |
* Only the forms $parameter and ${parameter} of parameter expansion are used inside an eval_gettext's argument (all other ones are forbidden). | * Enkel de voorkomens $parameter en ${parameter} van een parameter expansie worden gebruikt binnen een ''eval_gettext'' argument (alle andere voorkomens zijn verboden). |
* Positional parameters, special parameters and command substitutions are *not* used inside a gettext's or eval_gettext's argument. | * Positionele parameters, speciale parameters en commando substituties worden *niet* gebruikt binnen een argument van ''gettext'' of ''eval_gettext''. |
| |
As a practical consequence of the two last rules, it is advisable that all positional parameters, special parameters, command substitutions and not allowed forms of parameter substitutions be assigned upstream to named variables, then expanded in the text string argument of eval_gettext or eval_negettext. | Een praktisch gevolg van met name de twee laatste vereisten, is het advies om alle positionele parameters, speciale parameters, commando substituties en niet-toegestane vormen van parameter substituties aan de "upstream" ontwikkelaars te melden om een variabele-naam toe te laten wijzen, en dan geëxpandeerd in de tekstreeks die als argument van ''eval_gettext'' of ''eval_negettext'' dient. |
| |
Tip: if a text string has been included as a msgid in a catalog of messages and is assigned to a named variable in a script, then the commands: "gettext $parameter" and "gettext ${parameter}" will output the translated string at run time, even though 'xgettext' would discard that command when parsing the script, because 'gettext' is used instead of 'eval_gettext'. This can be handy. In this case the parameter expansion should not be escaped. | Tip: als een tekstreeks aanwezig is als een "msgid" in een berichten catalogus en toegewezen aan een variabele-naam in een script, dan zullen de commando's: "''gettext $parameter''" en "''gettext ${parameter}''" de vertaalde tekst uitgeven tijdens de script-executie (runtime), zelfs wanneer '''xgettext''' dat commando zo negeren bij het verwerken van het script, omdat '''gettext''' gebruikt wordt in plaats van '''eval_gettext'''. Dit kan handig zijn. In dat geval moet de parameter expansie niet ge-escaped worden. |
| |
| |
=== Markeer berichten om te lokaliseren === | === Markeer berichten om te lokaliseren === |
| |
I recommend to mark messages: | Aanbevolen wordt om de volgende tekstberichten te markeren: |
* arguments of a not redirected 'echo' command | * argumenten van een niet omgeleid '''echo''' commando. |
* arguments of redirected 'echo' commands whenever a further processing displays it on user's screen | * argumenten van omgeleide '''echo''' commando's indien in latere instantie de tekst toch op het scherm van de gebruiker wordt afgebeeld. |
* arguments of other commands which displays the message, for instance the 'dialog' program | * argumenten van andere commando's die het tekstbericht tonen, bijvoorbeeld het '''dialog''' programma. |
| |
On the contrary I recommend not to mark: | In tegenstelling daarmee is het aan te raden om de volgende niet te markeren: |
* comments intended for readers of the script, | * commentaren bedoeld voor lezers van het script, |
* text string whose value will be processed later, for instance as arguments of a 'case' compound command, or <tag> arguments of a dialog --menu' command. | * tekstreeks wiens waarde later zal worden verwerkt, bijvoorbeeld als argumenten voor een '''case''' samengesteld commando, of <tag> argumenten van een '''dialog --menu''' commando. |
| |
Sometimes the shell script writes other shell scripts. | Soms schrijft het shell script andere (nieuwe) shell scripts. |
| |
Then the developer or maintainer have to decide on a case by case basis what to mark depending on the intended scope of internationalization. | Dan zal de ontwikkelaar of maintainer van geval tot geval moeten beslissen wat er gemarkeerd moet worden, afhankelijk van de reikwijdte van de voorgenomen internationalisatie. |
| |
=== Gebruik 'xgettext' om een sjabloon-catalogus van berichten te produceren === | === Gebruik 'xgettext' om een sjabloon-catalogus van berichten te produceren === |
| |
The choice to produce only one POT file for the software as a whole or to make one POT files per set of scripts have to be made, considering for instance which choice will minimize maintenance work, how localizations work can be organized, relative frequency of updates for the different sets of scripts which comprise the software, and the relevance of distinguishing groups of features like setup vs configuration vs package management. | Een keuze moet worden gemaakt om een enkel POT bestand te maken voor de software als geheel, danwel een apart POT bestand voor verschillende verzamelingen scripts. Overwegingen zullen zijn, welke keuze minimaliseert het onderhoudswerk, hoe kan het werk aan de localisaties het beste worden geörganiseerd, wat is de relatieve frequentie van de wijzigingen op de verschillende verzamelingen van scripts die samen de software vormen, en de relevantie van de onderscheidende features zoals setup versus configuratie versus pakketbeheer. |
| |
I'm inclined to produce only one POT file, but the choice is yours. | |
| |
If the software comprises of numerous scripts located in different places or included in several packages, it can be handy to collect a copy of all scripts in a single directory, and/or to register in a text file a list of all of them with their paths. | De auteur produceert gewoonlijk een enkel POT bestand, maar iedereen moet zijn eigen afwegingen maken. |
| |
The POT file will be generated using the 'xgettext' command (see the manual or 'xgettext --help' for details). | indien de software bestaat uit een veelvoud van scripts die op verschillende plaatsen staan of opgenomen zijn in verschillende pakketten, kan het voordelig zijn om een kopie van alle scripts te verzamelen in een enkele directory, en/of in een apart tekstbestand al deze scripts te noteren inclusief hun padnamen. |
| |
Include following options in the command:<code> | Het POT bestand wordt gegenereerd met het '''xgettext''' commando (zie de handleiding of '''xgettext --help''xgettext --help' voor de details). |
-L Shell (of course!) | |
--strict (to facilitate checks and management of the messages catalogs) | |
-c (to include comments useful for the translators in the POT file) | |
-n (to identify the source file and the line number of each message. | |
This is the default.)</code> | |
| |
Once the POT file is generated you could check that it includes entries for all *gettext invocation in shell script(s). | Neem de volgende opties mee in het commando: <code> |
| -L Shell (vanzelfsprekend!) |
| --strict (ter ondersteuning van controles en beheer van de berichten catalogi) |
| -c (om commentaren in het POT bestand op te nemen die nuttig zijn voor de vertalers) |
| -n (identificeert het bronbestand en het regelnummer van ieder tekstbericht. |
| Dit is de standaard.) |
| </code> |
| |
| Wanneer het POT bestand eenmaal gegenereerd is moet je controleren dat het secties bevat voor alle ''*gettext'' aanroepen in de shell script(s). |
==== Localisatie proces ==== | ==== Localisatie proces ==== |
| |
Once the POT file is available, the 'msginit' command writes a PO file for each target language. | Wanneer het POT bestand klaar is, genereert het '''msginit''' commando daaruit een PO bestand voor iedere doel-taal. |
| |
In PO files the "msgid" strings should never be modified, otherwise the translation won't occur at run time. | In PO bestanden mogen de "msgid" tekstreeksen nooit gewijzigd worden, omdat er anders helemaal geen vertaling zal plaatsvinden tijdens de uitvoering van het script (runtime). |
| |
The 'msgcmp' command allow to checks each PO file against the POT after translation, to make sure all messages are translated. | Met het '''msgcmp''' commando kun je na de vertaalslag ieder PO bestand controleren tegen het POT bestand, om je te verzekeren dat alle tekstberichten vertaald zijn. |
| |
The translator can use the 'msgfmt' command to check the layout of the translated text. | De vertaler kan het '''msgfmt''' commando gebruiken om de layout van de vertaalde tekst te verifiëren. |
| |
The PO file should be carefully saved somewhere, as it will be needed for subsequent maintenance (it is still possible to 'msgunfmt' a MO file to re-create a PO file but then you would loose the context, which would make it almost useless). | Het PO bestand moet zorgvuldig bewaard worden, omdat dit opnieuw nodig is wanneer er onderhoud gepleegd wordt op de vertaling (het is mogelijk om met het '''msgunfmt''' commando uit een MO bestand een PO bestand te re-creëren maar daarbij gaat wel de context verloren, waardoor het resultaat nagenoeg onbruikbaar is). |
| |
The checked PO file is handed over to the maintainer, who runs 'msgfmt' to produce the MO file, then installs it. | Het gecontroleerde PO bestand wordt overgedragen aan de maintainer, die dan '''msgfmt''' gebruikt om het MO bestand te produceren en te installeren. |
| |
==== Gebruik ==== | ==== Gebruik ==== |