Last active
June 2, 2025 05:36
-
-
Save ku-enza/50fbfc73a7510bc2ff86adeb761bdf42 to your computer and use it in GitHub Desktop.
Shell script to extract t() function translations in drupal custom module and generate .pot file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Shell script to extract $this->t() function translations in drupal 8+ custom module and generate .pot file | |
| # Extract from .php .module .js .twig from current custom module folder | |
| # Exclude .min.js for js libraries | |
| # Put this in your module folder, make it executable : chmod +x generate_pot.sh , run it | |
| # Feel free to improve it | |
| # Define the regex patterns for each file type | |
| php_t_regex="\$this->t\(\s*'([^']*(?:@[a-zA-Z0-9_]+[^']*)*)'\s*(?:,\s*\[[^\]]*\])?\s*\)" | |
| twig_t_regex="{{\s*['\"]([^'\"]*(?:@[a-zA-Z0-9_]+[^'\"]*)*)['\"]\s*\|?\s*t\s*(?:\(\s*\{(?:[^\}]*)\}\s*\)|\(\s*\{[^\}]*\}?\s*\))?(?:\.\s*t\(\s*\{(?:[^\}]*)\}\s*\))?\s*}}" | |
| twig_trans_regex="{{\s*['\"]([^'\"]*)['\"]\s*\|\s*trans\s*}}|{%\s*trans\s*%}\s*((?:(?!{%\s*endtrans\s*%}).)*)\s*{%\s*endtrans\s*%}|{%\s*trans\s*%}\s*((?:(?!{%\s*plural\s*[^%]*%\s*).)*)\s*{%\s*plural\s*([^%]*)%\s*}\s*((?:(?!{%\s*endtrans\s*%}).)*)\s*{%\s*endtrans\s*%}" | |
| js_regex="Drupal\.t\(\s*['\"](.+?)['\"]\s*\)" | |
| js_regex_a="Drupal\.t\(\s*['\"](.+?)['\"],\s*{\s*['\"]@[^'\"]*['\"]:\s*[^,}]*[,\s}]" | |
| js_regex_p="Drupal\.formatPlural\(\s*[^,]*\s*,\s*['\"](.+?)['\"]\s*,\s*['\"](.+?)['\"]\s*\)" | |
| # Initialize the .pot file | |
| output_file="translations.pot" | |
| # Function to list all files used to extract translations | |
| function list_files() { | |
| file_type=$1 | |
| name_pattern=$2 | |
| find . -type f -name "$name_pattern" -print0 | sort -z | xargs -0 -I {} echo "# {}" | |
| } | |
| # Get the custom module name from the .info.yml file | |
| module_name=$(grep -oP "name:\s*\K[^\n]+" *.info.yml | tr '[:lower:]' '[:upper:]' | tr ' ' '_' | sed 's/_$//') | |
| # Get the current date and time | |
| current_date=$(date +"%Y-%m-%d %H:%M%z") | |
| # Write the header to the .pot file | |
| { | |
| echo "# \$Id$" | |
| echo "#" | |
| echo "# LANGUAGE translation of Drupal 9 module" | |
| echo "# Copyright YEAR NAME <EMAIL@ADDRESS>" | |
| echo "# Generated from files:" | |
| list_files "php" "*.php" | |
| list_files "php" "*.module" | |
| list_files "twig" "*.twig" | |
| list_files "js" "*.js" "! -name *.min.js" | |
| echo | |
| echo "# xx translation of $module_name" | |
| echo | |
| echo "\"Project-Id-Version: $module_name v1\\n\"" | |
| echo "\"POT-Creation-Date: $current_date\\n\"" | |
| echo "\"PO-Revision-Date: $current_date\\n\"" | |
| echo "\"Last-Translator: NAME <EMAIL@ADDRESS>\\n\"" | |
| echo "\"Language-Team: LANGUAGE <EMAIL@ADDRESS>\\n\"" | |
| echo "\"MIME-Version: 1.0\\n\"" | |
| echo "\"Content-Type: text/plain; charset=utf-8\\n\"" | |
| echo "\"Content-Transfer-Encoding: 8bit\\n\"" | |
| echo "\"Plural-Forms: nplurals=2; plural=(n > 1);\\n\"" | |
| echo "\"X-Generator: Custom script v.01\\n\"" | |
| echo | |
| echo "msgid \"\"" | |
| echo "msgstr \"\"" | |
| echo | |
| } > "$output_file" | |
| # Helper function to extract the strings and append them to the .pot file | |
| function extract_strings() { | |
| file_type=$1 | |
| regex=$2 | |
| name_pattern=$3 | |
| find . -type f -name "$name_pattern" ! -name "*.min.js" -print0 | while IFS= read -r -d '' file; do | |
| matches=$(perl -ne "print \"\$1\n\" while (/$regex/g);" "$file" | sort -u) | |
| if [ -n "$matches" ]; then | |
| echo -e "# ${file}\n# $(printf '%0.s-' $(seq 1 ${#file}))\n" >> "$output_file" | |
| echo "$matches" | while read -r match; do | |
| echo -e "msgid \"$match\"\nmsgstr \"\"\n" >> "$output_file" | |
| done | |
| fi | |
| done | |
| } | |
| # Helper function to remove duplicate msgid entries | |
| function remove_duplicates() { | |
| awk ' | |
| /^msgid/ { | |
| if (!msgid[$0]++) | |
| else | |
| getline; getline | |
| } | |
| /^msgstr/ { print } | |
| !/^(msgid|msgstr)/ { print } | |
| ' "$output_file" > "$output_file.tmp" && mv "$output_file.tmp" "$output_file" | |
| } | |
| # Extract strings from each file type | |
| extract_strings "php" "$php_t_regex" "*.php" | |
| extract_strings "php" "$php_t_regex" "*.module" | |
| extract_strings "twig" "$twig_t_regex" "*.twig" | |
| #extract_strings "twig" "$twig_trans_regex" "*.twig" | |
| extract_strings "js" "$js_regex" "*.js" | |
| #extract_strings "js" "$js_regex_a" "*.js" | |
| #extract_strings "js" "$js_regex_p" "*.js" | |
| # Remove duplicate lines except for those that start with 'msgstr ""', except empty lines \n and line starting with # | |
| remove_duplicates | |
| # Remove double empty lines | |
| sed -i '/^$/N;/^\n$/D' "$output_file" |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
change first msgid msgstr position