Fermer

décembre 15, 2020

Outil de copie de langue avec les extensions Sitecore Powershell (mise à jour 2020)


Initialement publié en 2018, j'ai décidé de mettre à jour ce message car le script a un peu évolué au fil des ans. Si vous n'êtes pas familier avec Powershell dans le contexte de Sitecore, alors je vous recommande vivement de consulter Extensions de Sitecore Powershell . Ce script, en particulier, nous l'avons utilisé sur plusieurs projets – et il permet à l'équipe de création de contenu de copier rapidement des langues sur plusieurs éléments de contenu en masse. À chaque nouveau projet que je lance, l'équipe me demande d'inclure cette fonctionnalité.

Cas d'utilisation

De n'importe où dans l'arborescence de contenu, je veux pouvoir cliquer avec le bouton droit sur un élément et choisir de copier sa langue. Je souhaite également pouvoir copier des sources de données et des sous-éléments. Voici comment vous devez y accéder et à quoi ressemblera le modal:

 Boîte de dialogue Copier la langue pour les auteurs de contenu

Explication

Pour créer cette fonctionnalité, j'ai ajouté un script de menu contextuel au Powershell de mon locataire bibliothèque de scripts. Cela peut également être une fonctionnalité de votre configuration Helix. Le mien ressemble à ceci:

 Copy Lang Script Access

 Covid 19

Tout d'abord, nous avons besoin d'une fonction qui nous permet d'extraire les sources de données d'un élément. Je vais le mettre en œuvre afin qu'il ignore les espaces réservés au-dessus du contenu de la page et au-dessous du contenu de la page, car je ne souhaite pas exécuter cette commande de copie sur mes extraits d'en-tête et de pied de page. Vous voudrez peut-être changer cela en fonction de vos pratiques d'assemblage.

 function GetItemDatasources {
    [CmdletBinding()]
    param ([Item] $ Item)
    # récupérer toutes les sources de données qui ne sont pas des éléments d'en-tête et de pied de page
    return Get-Rendering -Item $ item -FinalLayout -Device (Get-LayoutDevice -Default)
        | Where-Object {-not [string] :: IsNullOrEmpty ($ _. Datasource)}
        | Where-Object {$ _. Placeholder -ne 'Au-dessus du contenu de la page'}
        | Where-Object {$ _. Placeholder -ne 'Sous le contenu de la page'}
        | ForEach-Object {Get-Item "$ ($ item.Database):" -ID $ _. Datasource}
} 

Ensuite, j'ai besoin du point d'entrée principal dans le programme. Puisqu'il s'agit d'un script de menu contextuel, l'utilisateur l'appelle en cliquant avec le bouton droit sur un élément dans l'arborescence. L'applet de commande get-location renverra l'élément sur lequel vous avez cliqué.

 Copier la bibliothèque de scripts Lang

 $ location = get-location 

Nous devons maintenant créer des options à afficher pour l'utilisateur. Je veux qu'ils choisissent des langues, un mode de copie et des options supplémentaires. C'est ce que fait toute cette logique.

 $ languages ​​= Get-ChildItem "master:  sitecore  system  Languages";
$ currentLanguage = [Sitecore.Context] :: Language.Name;
$ langOptions = @ {};
foreach ($ lang dans $ languages) {
    $ langOptions [$lang.Name] = $ lang.Name;
}
$ ifExists = @ {};
$ ifExists ["Append"] = "Ajouter";
$ ifExists ["Skip"] = "Ignorer";
$ ifExists ["Overwrite Latest"] = "OverwriteLatest"; 

Une fois mes arguments prêts, je peux continuer et inviter l'utilisateur avec une boîte de dialogue. Dans cette boîte de dialogue, j'ai ajouté des colonnes, du texte d'aide, etc. À la toute fin, je veux m'assurer qu'ils ont appuyé sur le bouton OK. Vous pouvez voir que si le $ result n'est pas défini sur «ok», alors nous quittons le script.

 $ result = Read-Variable -Parameters `
    @ {Name = "originLanguage"; Valeur = $ currentLanguage; Title = "Langue d'origine"; Options = $ langOptions; },
    @ {Name = "destinationLanguages"; Title = "Langue (s) de destination"; Options = $ destinationOptions; Editor = "liste de contrôle"; },
    @ {Name = "includeSubitems"; Valeur = $ false; Title = "Inclure les sous-éléments"; Colonnes = 4;},
    @ {Name = "includeDatasources"; Valeur = $ false; Title = "Inclure les sources de données"; Colonnes = 4},
    @ {Name = "includeSnippets"; Valeur = $ false; Title = "Inclure les sources de données d'extraits de code"; Colonnes = 4},
    @ {Name = "ifExists"; Valeur = "Ignorer"; Title = "If Exists"; Options = $ ifExists; Tooltip = "Ajouter: Créer une nouvelle version linguistique avec le contenu copié. 
Ignorer: ne rien faire si la destination a la version linguistique.
Écraser la dernière: écraser la dernière version linguistique avec le contenu copié."; } ` -Description "Sélectionnez une langue d'origine et de destination, avec des options sur la façon de réaliser la copie" ` -Titre "Copy Language" -Width 650 -Height 660 -OkButtonName "Proceed" -CancelButtonName "Cancel" -ShowHints if ($ result -ne "ok") { Sortie }

Nous devons maintenant calculer les éléments sélectionnés par l'utilisateur en fonction des paramètres choisis (inclure les sous-éléments, inclure les sources de données, inclure les sources de données d'extraits de code, etc.). Nous stockerons la liste des éléments dans un objet appelé $ items, et nous supprimerons les doublons à la fin.

 $ items = @ ()
 
$ items + = Get-Item $ location
 
# ajouter des sous-éléments facultatifs
if ($ includeSubitems) {
    $ items + = Get-ChildItem $ location -Recurse
}
 
# ajouter des sources de données facultatives
if ($ includeDatasources) {
    Foreach ($ item en $ items) {
        $ items + = GetItemDatasources ($ item)
    }
}
 
# ajouter des sous-éléments facultatifs à la source de données
if ($ includeSnippets) {
    $ items + = $ items | Where-Object {$ _. TemplateName -eq 'MySite Snippet'} | ForEach-Object {GetItemDatasources ($ _)}
}
 
# Supprimez tous les doublons, en fonction de votre ID
$ items = $ items | Sort-Object -Property 'ID' -Unique 

À ce stade, je veux que l'utilisateur confirme que j'ai extrait les éléments nécessaires. Ils ne peuvent pas vraiment voir une liste d’éléments, mais ils doivent avoir une idée approximative du nombre d’éléments qu’ils sont sur le point de traduire. Par exemple, s'ils pensent traduire 5 éléments, mais que la liste revient avec 1200 éléments, alors c'est une chance pour eux d'annuler l'exécution et de réessayer.

 $ message = "Vous êtes sur le point de mettre à jour  $ ($ items.Count) article (s)  avec les options suivantes: 
" $ message + = "
" $ message + = "" $ message + = "" $ message + = "" $ message + = "" $ message + = "" $ message + = "" $ message + = "
Langue d'origine: $ originLanguage
Langues de destination: $ destinationLanguages ​​
Inclure les sous-éléments: $ includeSubitems
Inclure les sources de données: $ includeDatasources
Inclure les sources de données d'extraits de code: $ includeSnippets
Méthode de copie: $ ifExists
" $ message + = "

Êtes-vous sûr?

" $ procéder = Afficher-Confirmer -Titre $ message if ($ procéder -ne 'oui') { Write-Host "Annulation" Sortie }

Au final, l'algorithme est assez simple. Tout ce que nous avons à faire est de prendre chaque élément et de l'exécuter via la commande Add-ItemLanguage, en passant les différentes options choisies par l'utilisateur.

 $ items | ForEach-Object {Add-ItemLanguage $ _ -Language $ originLanguage -TargetLanguage $ destinationLanguages ​​-IfExist $ ifExists} 

Le script complet

Voici le script complet avec lequel j'ai fini, dans toute sa splendeur.

 fonction GetItemDatasources {
    [CmdletBinding()]
    param ([Item] $ Item)
 
    # récupérer toutes les sources de données qui ne sont pas des éléments d'en-tête et de pied de page
    return Get-Rendering -Item $ item -FinalLayout -Device (Get-LayoutDevice -Default) |
        Where-Object {-not [string] :: IsNullOrEmpty ($ _. Datasource)} |
        Where-Object {$ _. Placeholder -ne 'Au-dessus du contenu de la page'} |
        Where-Object {$ _. Placeholder -ne 'Sous le contenu de la page'} |
        ForEach-Object {Get-Item "$ ($ item.Database):" -ID $ _. Datasource}
        # ForEach-Object {Write-Host ($ _ | Format-List | Out-String)}
}
 
$ location = get-location

$ user = Get-User -Current

$ languages ​​= Get-ChildItem "master:  sitecore  system  Languages"

$ currentLanguage = [Sitecore.Context] :: Language.Name
 
$ langOptions = @ {};
$ destinationOptions = @ {};
 
foreach ($ lang dans $ languages) {
    $ langOptions [$lang.Name] = $ lang.Name
    if (Test-ItemAcl -Identity $ user -Path $ lang.Paths.Path -AccessRight language: write) {
        $ destinationOptions [$lang.Name] = $ lang.Name
    }
}
 
$ ifExists = @ {};
$ ifExists ["Append"] = "Ajouter";
$ ifExists ["Skip"] = "Ignorer";
$ ifExists ["Overwrite Latest"] = "OverwriteLatest";
 
$ result = Read-Variable -Parameters `
    @ {Name = "originLanguage"; Valeur = $ currentLanguage; Title = "Langue d'origine"; Options = $ langOptions; },
    @ {Name = "destinationLanguages"; Title = "Langue (s) de destination"; Options = $ destinationOptions; Editor = "liste de contrôle"; },
    @ {Name = "includeSubitems"; Valeur = $ false; Title = "Inclure les sous-éléments"; Colonnes = 4;},
    @ {Name = "includeDatasources"; Valeur = $ false; Title = "Inclure les sources de données"; Colonnes = 4},
    @ {Name = "includeSnippets"; Valeur = $ false; Title = "Inclure les sources de données d'extraits de code"; Colonnes = 4},
    @ {Name = "ifExists"; Valeur = "Ignorer"; Title = "If Exists"; Options = $ ifExists; Tooltip = "Ajouter: Créer une nouvelle version linguistique avec le contenu copié. 
Ignorer: ne rien faire si la destination a la version linguistique.
Écraser la dernière: écraser la dernière version linguistique avec le contenu copié."; } ` -Description "Sélectionnez une langue d'origine et de destination, avec des options sur la façon de réaliser la copie" ` -Titre "Copy Language" -Width 650 -Height 660 -OkButtonName "Proceed" -CancelButtonName "Cancel" -ShowHints if ($ result -ne "ok") { Sortie } Write-Host "originLanguage = $ originLanguage" Write-Host "destinationLanguages ​​= $ destinationLanguages" $ items = @ () $ items + = Get-Item $ location # ajouter des sous-éléments facultatifs if ($ includeSubitems) { $ items + = Get-ChildItem $ location -Recurse } # ajouter des sources de données facultatives if ($ includeDatasources) { Foreach ($ item en $ items) { $ items + = GetItemDatasources ($ item) } } # ajouter des sous-éléments facultatifs à la source de données if ($ includeSnippets) { $ items + = $ items | Where-Object {$ _. TemplateName -eq 'MySite Snippet'} | ForEach-Object {GetItemDatasources ($ _)} } # Supprimez tous les doublons, en fonction de votre ID $ items = $ items | Sort-Object -Property 'ID' -Unique $ items | ForEach-Object {Write-Host ($ _. ItemPath | Sort-Object | Format-List | Out-String)} $ message = "Vous êtes sur le point de mettre à jour $ ($ items.Count) élément (s) avec les options suivantes:
" $ message + = "
" $ message + = "" $ message + = "" $ message + = "" $ message + = "" $ message + = "" $ message + = "" $ message + = "
Langue d'origine: $ originLanguage
Langues de destination: $ destinationLanguages ​​
Inclure les sous-éléments: $ includeSubitems
Inclure les sources de données: $ includeDatasources
Inclure les sources de données d'extraits de code: $ includeSnippets
Méthode de copie: $ ifExists
" $ message + = "

Êtes-vous sûr?

" $ procéder = Afficher-Confirmer -Titre $ message if ($ procéder -ne 'oui') { Write-Host "Annulation" Sortie } Write-Host "Procéder à l'exécution" $ items | ForEach-Object {Add-ItemLanguage $ _ -Language $ originLanguage -TargetLanguage $ destinationLanguages ​​-IfExist $ ifExists}

Quelques pointeurs supplémentaires…

Teste toujours vos scripts avant de les mettre en production. Cela suppose également que vous disposez d'une fonctionnalité similaire aux extraits de code de SCORE ou SXA. Vous pouvez facilement supprimer cette partie si vous en avez besoin. J'espère que cela vous aidera dans votre voyage Sitecore…

À propos de l'auteur <! -: dmccurry, Architecte de solutions ->

Je suis un développeur Sitecore certifié, un singe de code et un nerd général . J'ai sauté dans l'espace .NET il y a 10 ans pour travailler sur des applications de classe entreprise et je n'ai jamais regardé en arrière. J'adore créer des choses, des Legos aux logiciels qui résolvent de vrais problèmes. Ai-je mentionné J'adore les jeux vidéo?

Plus de cet auteur




Source link