Once an event expires, we need to automatically stop showing those events in website. To do this, we created a PowerShell script and automated running of this script using a Sitecore scheduler.
Lets look at the steps that we followed :
Created PowerShell script as per our requirement like below. This script takes event parent item path and language id as input . Then iterates through children of that item & checks if the eventenddate field of each child item is less than today. If its an expired event, it makes that event unpublishable and publishes all child event
2. Go to script library under following path and save above created PS script- /sitecore/system/Modules/PowerShell/Script Library
3. Go to /sitecore/system/Tasks/Schedules and create a “PowerShell scripted task Scheduler”.
4. Name it as per convention, choose the script to execute(which we previously created), choose start and end date & choose time interval
5. If you have multiple schedulers running in Sitecore instance, make sure to choose “Async” checkbox . This option enables your Scheduler tasks to run asynchronous.
Hope it helps you!!
HAPPY SITECORING!! LETS MAKE SITECORE SIMPLE!!
Share the article to your LinkedIN Network using below options
It is convenient to have a handbook of frequently used Sitecore PowerShell scripts. Right?
That is exactly what am trying to do with this post.
PS: I will keep on adding new & useful scripts to this page as I come across. So, Go ahead and bookmark this URL . You can always comeback whenever you need to check available scripts. Variables are wrapped with {} in example scripts.
Copy content from one language to another for an Item’s children. You can skip if a version exists in target language by replacing OverwriteLatest with Skip Scenario – You have German-Germany language version and need that to be German-Switzerland content as well. So SourceLanguageID could be “de-DE” and TargetLanguageID could be “de-CH” Code – $path = “master:{YourItemPath}” Get-ChildItem $path -Recurse | ForEach-Object { Add-ItemLanguage $_ -Language “{SourceLanguageID}” -TargetLanguage “{TargetLanguageID}” -IfExist OverwriteLatest }
Remove a particular language version from an Item’s children Scenario – You want to remove French-France language from an item’s children . So LanguageID could be “fr-FR” Code – $path = “master:{YourItemPath}” @(Get-Item $path) + (Get-ChildItem $path -Recurse) | Remove-ItemLanguage -Language “{LanguageID}”
Publish item with sub items for a particular language . You can pass your approved state workflow state ID and publish items. This will reduce manual work needed to change workflow state
In recent times IT professionals or someone who has interest in Technology and stuffs would definitely heard about ChatGPT . Right? Of course a BIG YES.
Onto my next question. Can we communicate with it & leverage its power to make something out of it in Sitecore? To my surprise it was so simple to do that via PowerShell.
Recently I was working on a POC about Semi-Automated Content Translation in Sitecore and found out this.
Problem statement : Translate a Sitecore Item’s field value from one language to another.
2) Create a template in Sitecore to define the fields to be translated & API key
3) Create a Translation settings item based on this template and add values (Fields to be translated & API key) under /sitecore/system/Modules/GPT Translation/GPT Translate Settings
4) Create a PowerShell module and add the following script
#Grab the Context Item
$sourceItem = Get-Item .
#Load our Settings including Languages and Fields to Translate
$settings = Get-Item "master:\sitecore\system\Modules\GPT Translation\GPT Translate Settings" -Language "en"
$apiKey = $settings["ChatGPT API Key"]
$filterFields = ([Sitecore.Data.Fields.MultilistField]$settings.Fields["Fields To Be Translated"]).GetItems()
$commonLanguages = Get-ChildItem -Item $settings -Language "en"
$fieldsOptions = @{}
$filterFields | ForEach-Object {
$fieldsOptions.Add($_.Name, $_.ID)
}
#Grab languages from the system
$languages = Get-ChildItem "master:\sitecore\system\Languages" -Language "en"
#Grab workflows from the system
$workflows = Get-ChildItem "master:\sitecore\system\Workflows" -Language "en"
$languageOptions = @{}
$languages | ForEach-Object {
$languageOptions.Add($_.Name, $_.Name)
}
$workflowOptions = @{}
$workflows | ForEach-Object {
$workflowOptions.Add($_.Name, $_.Name)
}
#Remove Current Language
$languageOptions.Remove($SitecoreContextItem.Language.Name)
$props = @{
Parameters = @(
@{Name="fieldsToTranslateOption"; Editor="Checklist"; Title="Choose which fields to translate"; Options=$fieldsOptions; Tooltip="This list is configurable."}
@{Name="languagesToTranslateOption"; Title="Choose which language to translate to."; Options=$languageOptions}
@{Name="workflowtobeapplied"; Title="Choose which workflow to apply for translated item."; Options=$workflowOptions}
)
Title = "GPT Translation"
Description = "Choose the right option."
Width = 600
Height = 400
ShowHints = $true
}
$res = Read-Variable @props
#We need to map our ISO Code (es-MX) to a friendly language (Spanish)
$languages | Foreach-Object {
$langCode = $_.Name
#Write-Host "LangCode:" $langCode "languagesToTranslateOption selected :" $languagesToTranslateOption
if($langCode -eq $languagesToTranslateOption)
{
$commonLang = $_.DisplayName
#Write-Host "Common Lang"$_.DisplayName
}
}
Write-Host "API Key:" $apiKey
Write-Host "Fields to Translate:" $fieldsToTranslateOption
Write-Host "Current Language:" $SitecoreContextItem.Language.Name
Write-Host "Selected Language:" $languagesToTranslateOption
Write-Host "Selected Language (Common):" $commonLang
Write-Host "Translating for: " $sourceItem.Name
Write-Host "Filter Count: " $filterFields.Count.ToString()
#If we didn't click OK, then it isn't OK!
if($res -ne "ok")
{
Show-Alert "Aborted"
Exit
}
#we need to make sure all the fields to translate exist on this item and remove the ones that don't
$filteredFields = New-Object -TypeName 'System.Collections.ArrayList'
$sourceItem.Fields | ForEach-Object {
$sourceField = $_
$filterFields | ForEach-Object {
if($_.ID -eq $sourceField.ID)
{
Write-Host "Found" $_.Name
$filteredFields.Add($_)
}
}
}
Write-Host "Translatable Fields Count: " $filteredFields.Count.ToString()
#Using our fields, let's create a list of translation objects we'll iterate through
$translations = New-Object -TypeName 'System.Collections.ArrayList'
$filteredFields | ForEach-Object {
$fieldDef = Get-Item -Path master: -ID $_.ID
$translationItem = @{
FieldID = $_.ID
Untranslated = $sourceItem.Fields[$_.ID].Value
Translated = ""
FieldType = $fieldDef.Type
}
$translations.Add($translationItem)
}
$translations | ForEach-Object {
$translationAsk = "Text"
#making RichText field type as markup so that it does not break
if($_.FieldType -eq "Rich Text")
{
$translationAsk = "markup"
}
#Removing unwanted quotes if any present in Untranslated text
if($_.Untranslated[0] -eq "`"" -and $_.Untranslated[($_.Untranslated.Length-1)] -eq "`"")
{
$_.Untranslated = $_.Untranslated.substring(1, ($_.Untranslated.Length -2)).Trim()
}
$headers = @{
Authorization = "Bearer " + $apiKey
}
#Generate our prompt
#Translate the following Text/HTML to Target Language
$data = @{
model = "gpt-3.5-turbo"
messages = @(
@{
role = "user"
content = "Translate the following " + $translationAsk + " to " + $commonLang + " `"" + $_.Untranslated + "`""
}
)
}
Write-Host "PayLoad is:" "Translate the following " $translationAsk " to " $commonLang $_.Untranslated
$Params = @{
Method = "POST"
Headers = $headers
Body = $data | ConvertTo-Json
Uri = "https://api.openai.com/v1/chat/completions"
ContentType = "application/json; charset=utf-8"
}
$result = (Invoke-RestMethod @Params).choices[0]
$_.Translated = $result.message.content
}
$targetItem = Add-ItemVersion -Item $sourceItem -TargetLanguage $languagesToTranslateOption
$workflows | ForEach-Object {
$workflw = $_.Name
#Write-Host $_.Name
if($workflw -eq $workflowtobeapplied)
{
$selectedworkflow = $_.ID
}
}
$itemId = Get-Item master: -ID $selectedworkflow
$workflowstates = Get-ChildItem $itemId.Paths.FullPath -Language "en"
$workflowstateOptions = @{}
$workflowstates | ForEach-Object {
$workflowstateOptions.Add($_.Name, $_.Name)
}
$props = @{
Parameters = @(
@{Name="workstatetobeapplied"; Title="Choose which workflow state needs to be applied for translated item."; Options=$workflowstateOptions}
)
Title = "GPT Translation"
Description = "Choose the right option."
Width = 600
Height = 400
ShowHints = $true
}
$res = Read-Variable @props
if($res -ne "ok")
{
Show-Alert "Aborted"
Exit
}
$workflows | ForEach-Object {
$workflw = $_.Name
#Write-Host $_.Name
if($workflw -eq $workflowtobeapplied)
{
$selectedworkflow = $_.ID
Write-Host "WorkflowID to be applied" $selectedworkflow
$itemId = Get-Item master: -ID $selectedworkflow
$workflowstates = Get-ChildItem $itemId.Paths.FullPath -Language "en"
$workflowstates | ForEach-Object {
$workstte = $_.Name
if($workstte -eq $workstatetobeapplied)
{
$selectedworkflowstate = $_.ID
}
}
}
}
Write-Host "Selected workflowstate :" $selectedworkflowstate
$targetItem.Editing.BeginEdit()
$translations | ForEach-Object {
Write-Host "Source:" $_.Untranslated
Write-Host "Dest:" $_.Translated
#we need to fix some encoding shenanigans
$bytes = [System.Text.Encoding]::GetEncoding(1252).GetBytes($_.Translated);
$fixed = [System.Text.Encoding]::UTF8.GetString($bytes).Trim();
#Removing unwanted quotes if any present
if($fixed[0] -eq "`"" -and $fixed[($fixed.Length-1)] -eq "`"")
{
$fixed = $fixed.substring(1, ($fixed.Length -2)).Trim()
}
Write-Host "Fixed:" $fixed
$targetItem[$_.FieldID] = $fixed
$targetItem.Fields["__workflow"].value=$selectedworkflow
$targetItem.Fields["__Workflow state"].Value =$selectedworkflowstate
}
$targetItem.Editing.EndEdit()
5) Right click on an item – choose the PowerShell script created, choose the fields to be translated, choose the target language, choose the workflow to be applied and in next window choose the work state.
We can customize the code above to add more cool features.
Recently, I had a requirement where we copied several items from one content node to a different one. So, we needed to update the workflow for these newly copied items.
Since it will be a tedious process to manually update the workflow of these items, I opted out the smart way. And that is: PowerShell script
PowerShell might look simple, but it is mighty powerful!
After a little bit of research and help from colleagues, managed to put together the below script. Note: this might need some extra sprinkle on it’s top as per your needs. But this will get the job done precisely.
#Put your item path here $Datapath = “master:/sitecore/content/….” #Put your workflow item’s Guid here $WorkflowID = “{….}” #Put your workstate item’s Guid here $ApprovedStateID=”{….}” #Put the Language ISO Code in here $langID=”en” #Following code updates the default workflow along with workflow and workstate $items = Get-ChildItem $Datapath -Language $langID -Recurse -Version * | Where-Object { $_.TemplateName -ne “Folder”} ($items)|ForEach-Object{ $_.Editing.BeginEdit() $_.Fields[“__workflow”].Value=$WorkflowID; $_.Fields[“__Default workflow”].Value =$WorkflowID; $_.Fields[“__Workflow state”].Value=$ApprovedStateID; $ItemId=$_.ID $lang=$_.Language $version=$_.Version echo “$ItemId $lang $version” $_.Editing.EndEdit() } Write-Host ‘completed updating workflow for Specified Items’
There is nothing really complex about it. It captures the workflow and workstate Item IDs and assign the value to child items of mentioned Datapath recursively. Only catch is that we did not apply it for folder items(as per our requirement).
One more point worth to mention here is that, this code recursively assigns the workflow & workstate to all numbered versions of the particular language version(“en”) .