Question Localisation d'un script en plusieurs langues

Plus d'informations
il y a 17 ans 2 mois #3759 par Jacques Barathon
Hello,

Pour info, je viens de mettre en ligne un nouveau billet sur mon blog, traitant de la fonctionnalité de \"script internationalization\" disponible dans la v2 CTP3.

janel.spaces.live.com/blog/cns!9B5AA3F6FA0088C2!416.entry

Cette fonctionnalité permet de fournir automatiquement des messages adaptés à la langue de l'utilisateur (attention: la traduction n'est pas automatique, c'est la sélection de la langue selon le contexte qui l'est :)).

N'hésitez pas à laisser un commentaire sur mon blog ou à répondre à ce fil si vous avez des remarques ou des questions.

Janel

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 2 mois #3769 par Laurent Dardenne
Sur le même sujet mais concernant la localisation des messages d'erreur de PS, voir ce script (Get-PSResourceString) .
Pour la V1 il reste possible de mettre en place un système de localisation basé sur un fichier de ressource et des hashtables. Cela demande un peu plus de code mais n'est pas vraiment pour débutant :unsure:

Sinon cette section Data est bien indépendante de la notion de \"script-Module\" ?
On peut l'utiliser dans un module pour découpler le code des données ?
Enfin si toutefois tu as testé cet aspect, de mon coté je n'ai pas encore pris le temps de creuser le sujet :whistle:

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 2 mois #3771 par Jacques Barathon
Fichtre, les exemples que tu fournis sont très intéressants mais en effet, ils sont très complexes à mettre en oeuvre.

Pour faire de la localisation avec la v1, j'aurais simplement pensé reprendre le principe utilisé dans la commandelette import-localizeddata de la v2, dont la difficulté technique essentielle réside dans la richesse potentielle du contenu des fichiers .psd1.

Or, dans 99% des cas de localisation on a simplement besoin d'énumérer des chaînes dans des hashtables (clé = nom de la variable, valeur = contenu de la variable), et pour ça il n'y a pas besoin de faire des choses très complexes. Il suffit de pointer sur le bon fichier en fonction de la culture, et de charger les couples clé/valeur dans le fichier en question. Si j'ai un peu de temps dans la journée j'écrirai une fonction que je publierai ici pour que vous regardiez si ça pourrait convenir.

Quant aux scripts/modules, oui c'est une notion totalement différente. Et à priori oui, on peut utiliser une section Data dans un module. Un module peut contenir scripts et DLL selon les besoins, donc pourquoi pas des sections Data et des sous-répertoires localisés. Mais moi non plus je n'ai pas testé.

Janel

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 2 mois #3772 par Jacques Barathon
Bon, voici une version simplissime au possible:

[code:1]
function import-localizeddata
{
param (
[string]$filename = [IO.Path]::GetFileNameWithoutExtension((split-path -leaf $myinvocation.MyCommand)),
[System.Globalization.CultureInfo]$UIculture = (get-UIculture)
)

$fullpath = $(split-path $myinvocation.ScriptName) + \"\$UIculture\$filename\" + \".psl1\"

$ht = @{}
get-content $fullpath | where {($_.TrimStart()) -ne \"\" -and ($_.TrimStart())[0] -ne \"#\"} | foreach {
$key, $value = $_.Split(\"=\", 2)
$ht.Add($key.Trim(), $value.TrimStart())
}
$ht
}
[/code:1]
La fonction ci-dessus permet d'importer des données selon la culture de la session en cours ou en précisant une culture particulière. Evidemment (c'était le but de l'exercice) ça marche avec la v1 de PowerShell.

Chaque fichier de données doit être placé dans un répertoire portant le nom de la culture (\"fr-FR\", \"en-US\", etc). Ce répertoire lui-même doit être placé dans le même répertoire que le script.

Par défaut, le fichier lu aura le même nom que le script, avec une extension différente: .psl1 (pour PowerShell Localization, v1 :)). Mais on peut préciser un autre nom de fichier. Attention à ne pas préciser l'extension, elle est rajoutée par la fonction!

Enfin, le contenu d'un fichier doit être sous la forme suivante:

<nom> = <valeur>

Pour faciliter la lecture du fichier, on peut ajouter des lignes vierges et des lignes de commentaire commençant par #.

Contrairement à la commandelette import-localizeddata de la v2, je ne passe pas le nom de la variable en paramètre. Ici, le contenu est retourné par la fonction sous la forme d'une hashtable qu'il revient à l'utilisateur de traiter comme il l'entend. A priori on affectera le résultat de la fonction à une variable.

Prenons un exemple. Dans mon répertoire c:/tests j'ai un script test-local.ps1 et deux répertoires, c:/tests/en-US et c:/tests/fr-FR. Chacun de ces deux répertoires contient un fichier test-local.psl1.

[code:1]
PS> get-content c:\tests\fr-FR\test-local.psl1
# culture \"fr-FR\"

Welcome = Bienvenue au jeu \"Devinez un jour\" !
Prompt = Tapez un nom de jour
Success = Vous avez deviné ! Toutes nos félicitations !

PS> get-content c:\tests\en-US\test-local.psl1
# culture \"en-US\"

Welcome = Welcome to the \"Guess a day\" game!
Prompt = Enter the name of any day
Success = You had it right! Congratulations!
[/code:1]
Dans le deuxième fichier j'ai ajouté des espaces pour montrer qu'on peut en ajouter en début de ligne sans qu'ils interfèrent dans la lecture du fichier.

Voyons maintenant le script test-local.ps1 :

[code:1]
PS> get-content c:\tests\test-local.ps1
param ([System.Globalization.CultureInfo]$myculture = (get-UIculture))

. c:\scripts\import-localizeddata.ps1

$messages = import-localizeddata -uiculture $myculture

$messages.Welcome
$messages.Prompt
$messages.Success
[/code:1]
Pour l'exercice, j'ai également sauvegardé la fonction import-localizeddata dans un fichier import-localizeddata.ps1, dans un répertoire c:/scripts. J'importe la fonction en début d'exécution de mon script, grâce à la technique de \"dot-sourcing\".

Enfin, voyons deux exemples d'usage du script :

[code:1]
PS> .\test-local
Bienvenue au jeu \"Devinez un jour\" !
Tapez un nom de jour
Vous avez deviné ! Toutes nos félicitations !
PS> .\test-local en-US
Welcome to the \"Guess a day\" game!
Enter the name of any day
You had it right! Congratulations!
[/code:1]
Voilà. On peut perfectionner la fonction pour qu'elle lise un tableau plus complexe, permettant par exemple d'ajouter des dimensions supplémentaires si on veut regrouper plusieurs tables de messages dans un même fichier. Mais en l'état ça me semble déjà couvrir 90% des besoins de localisation.

Commentaires bienvenus. Je posterai tout ça sur mon blog dans la journée.

Janel<br><br>Message édité par: janel, à: 20/01/09 13:07

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 2 mois #3773 par Laurent Dardenne
janel écrit:

Or, dans 99% des cas de localisation on a simplement besoin d'énumérer des chaînes dans des hashtables (clé = nom de la variable, valeur = contenu de la variable), et pour ça il n'y a pas besoin de faire des choses très complexes.

Dans mons cas l'objectif d'origine était d'automatiser la génération de fichier ressources, et une fois terminé je me suis dit que cela pouvait éventuellement servir à une localisation.
Ta solution est bien mieux adaptée car l'objectif est clairement établi.
En tout cas,et comme on dit au billard, belle bille !

Peut-être qu'un Select-string + une regex serait plus adapté pour, mais je n'ai pas testé :

get-content $fullpath | where ...

Et proposer un switch pour gérer ou non les espaces, ainsi on peut récupérer le texte brut.

janel écrit:

mais en effet, ils sont très complexes à mettre en oeuvre.

Tu peux préciser ?<br><br>Message édité par: Laurent Dardenne, à: 20/01/09 14:44

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 2 mois #3774 par Jacques Barathon
Laurent Dardenne écrit:

Peut-être qu'un Select-string + une regex serait plus adapté pour, mais je n'ai pas testé


Peut-être, ça ne m'est pas venu à l'esprit. Je suis allé au plus simple, et en général je n'utilise les regex que lorsque je ne vois pas de solution simple en recherche littérale. Or, ici get-content, un simple filtrage et un Split(\&quot;=\&quot;,2) faisaient l'affaire! :)

Et proposer un switch pour gérer ou non les espaces, ainsi on peut récupérer le texte brut.


Hmmm, pourquoi pas, mais peux-tu préciser dans quel cas ça te serait utile?

janel écrit:

mais en effet, ils sont très complexes à mettre en oeuvre.

Tu peux préciser ?


Le principe des ressources basé sur les streams NTFS nécessite d'installer NTFS.DLL sur les postes. Egalement, le stockage des ressources dans ces streams est totalement invisible pour la plupart des programmes, ce qui peut provoquer des pertes de données si, par exemple, on fait un malencontreux copier/coller du fichier sans penser à récupérer ses streams. Enfin, il faut penser à toujours déposer un tel fichier sur une partition NTFS sous peine de voir tous ses streams disparaître à tout jamais.

A part ça, en testant ma fonction sur un poste équipé de la v2 j'ai constaté qu'elle ne marchait pas, à cause de la variable $myinvocation.ScriptName qui n'est pas renseignée dans la v2... Galère. Ma solution est donc propre à la v1, alors que j'aurais voulu qu'elle soit universelle. A creuser. Je publierai la version corrigée dès que possible.

Janel<br><br>Message édité par: janel, à: 20/01/09 15:18

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.071 secondes
Propulsé par Kunena