Applescript To Google Translate iOS Projects
Translating your iOS projects can often be a painful process, so I wrote a little Applescript to help me translate the Ushahidi iOS app.
The script extracts phrases from your project with genstrings and NIB files with ibtool, calls the Google Translate service for each phrase, writes the translated text to file and then re-imports those phrases back into NIB files in the target language folder.
translateProject(choose folder with prompt "Select Project Source Folder", ¬
choose folder with prompt "Select Localization Destination Folder", ¬
display dialog "Enter Destination Language Code" default answer "")
on translateProject(projectFolder, localizationFolder, languageCodeDialog)
set languageCode to languageCodeDialog's text returned
if length of languageCode is equal to 0 then
display dialog "Language Code Required"
else
set englishFolder to createFolder(localizationFolder, "en.lproj")
do shell script "find " & quoted form of (POSIX path of projectFolder) & " -name '*.m' " & ¬
" | xargs genstrings -o " & quoted form of (POSIX path of localizationFolder & "en.lproj")
set nibFiles to filesWithExtension(projectFolder, ".xib")
repeat with nibFile in nibFiles
set nibFile to parseNib(nibFile, englishFolder)
end repeat
set languageFolder to createFolder(localizationFolder, (languageCode & ".lproj"))
repeat with englishFile in filesWithExtension(englishFolder, ".strings")
set languageFileName to getFileName(englishFile)
set languageFilePath to (languageFolder as text) & languageFileName as text
if fileExists(languageFilePath) is false then
set languageFile to writeFile(languageFolder, languageFileName, "", false)
end if
set fileLines to paragraphs of readFile(englishFolder, languageFileName)
repeat with fileLine in fileLines
if length of fileLine is greater than 0 then
set englishKey to parseKey(fileLine)
set englishText to parseValue(fileLine)
if length of englishText is greater than 0 then
if fileContainsText(languageFolder, languageFileName, "\"" & englishKey & "\" = ") is false then
set encodedText to encodeText(englishText, true, true)
set responseText to googleTranslate(encodedText, languageCode)
set translatedText to parseJson(responseText, "translatedText")
repeat until length of translatedText is greater than 0
set errorMessage to parseJson(responseText, "responseDetails")
if length of errorMessage is greater than 0 then
display dialog "Oops!" & space & errorMessage & space & "(Wait a few minutes, then click OK to continue)"
else
display dialog "Oops!" & space & responseText & space & "(Wait a few minutes, then click OK to continue)"
end if
set responseText to googleTranslate(encodedText, languageCode)
set translatedText to parseJson(responseText, "translatedText")
end repeat
set translatedLine to "\"" & englishKey & "\" = \"" & (translatedText as Unicode text) & "\";" as Unicode text
writeFile(languageFolder, languageFileName, translatedLine & return, true)
end if
end if
end if
end repeat
end repeat
repeat with nibFile in nibFiles
importNib(nibFile, languageFolder)
end repeat
display dialog "Translation Complete"
end if
end translateProject
on parseNib(filePath, targetFolder)
set fileName to getFileName(filePath)
set fileNameWithoutExtension to replaceCharacters(fileName, ".xib", "")
set stringsPath to POSIX path of targetFolder & fileNameWithoutExtension & ".strings"
set sourceNib to POSIX path of filePath
do shell script "ibtool --export-strings-file" & space & ¬
quoted form of stringsPath & space & ¬
quoted form of sourceNib
return stringsPath
end parseNib
on importNib(filePath, targetFolder)
if fileExists(filePath) then
set fileName to getFileName(filePath)
set fileNameWithoutExtension to replaceCharacters(fileName, ".xib", "")
set stringsPath to POSIX path of targetFolder & fileNameWithoutExtension & ".strings"
set targetNib to POSIX path of targetFolder & fileName
set sourceNib to POSIX path of filePath
do shell script "ibtool --strings-file" & space & ¬
quoted form of stringsPath & space & "--write" & space & ¬
quoted form of targetNib & space & ¬
quoted form of sourceNib
end if
end importNib
on getFileName(filePath)
set {name:fileName} to info for file filePath without size
return fileName
end getFileName
on filesWithExtension(fileFolder, fileExtension)
set fileList to {}
tell application "Finder"
set filePaths to every file of entire contents of folder fileFolder as list
repeat with filePath in filePaths
if (filePath as text) ends with fileExtension then
set end of fileList to filePath as text
end if
end repeat
end tell
return fileList
end filesWithExtension
on fileContainsText(fileFolder, fileName, textString)
set fileLines to paragraphs of readFile(fileFolder, fileName)
repeat with fileLine in fileLines
if textString is in fileLine then
return true
end if
end repeat
return false
end fileContainsText
on createFolder(parentFolder, folderName)
tell application "Finder"
if not (exists folder folderName of parentFolder) then
make new folder at parentFolder with properties {name:folderName}
end if
return folder folderName of parentFolder as text
end tell
end createFolder
on writeFile(fileFolder, fileName, textString, shouldAppend)
tell application "Finder"
set filePath to (fileFolder as text) & fileName as text
try
set fileAccess to open for access file filePath with write permission
if shouldAppend is false then
set eof of fileAccess to 0
write (ASCII character 254) & (ASCII character 255) to fileAccess starting at eof -- UTF-16 BOM
else
set fileDoesExist to exists file filePath
if fileDoesExist is false then
set eof of fileAccess to 0
write (ASCII character 254) & (ASCII character 255) to fileAccess starting at eof -- UTF-16 BOM
end if
end if
write textString to fileAccess starting at eof as Unicode text
close access fileAccess
on error
try
close access file filePath
end try
end try
return filePath as text
end tell
end writeFile
on readFile(fileFolder, fileName)
tell application "Finder"
set filePath to (fileFolder as text) & fileName as text
try
set fileAccess to open for access file filePath
set textContents to read fileAccess as Unicode text
close access fileAccess
return textContents
on error
try
close access file filePath
end try
end try
return ""
end tell
end readFile
on fileExists(filePath)
tell application "Finder"
try
if exists file filePath then
return true
else
return false
end if
on error
return false
end try
end tell
return false
end fileExists
on googleTranslate(textString, codeString)
return do shell script "/usr/bin/curl" & space & ¬
"'http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&langpair=en|" & codeString & "&q=" & quoted form of textString & "'"
end googleTranslate
on parseKey(textString)
if (textString does not start with "/*") then
set AppleScript's text item delimiters to "="
set textItems to text items of textString
set AppleScript's text item delimiters to ""
if (count of textItems) > 1 then
set textItem to item 1 of textItems
set AppleScript's text item delimiters to "\""
set textValue to text items of textItem
set AppleScript's text item delimiters to ""
if (count of textValue) > 1 then
return trimCharacters((item 2 of textValue), "\"") as Unicode text
end if
end if
end if
return ""
end parseKey
on parseValue(textString)
if (textString does not start with "/*") then
set AppleScript's text item delimiters to "="
set textItems to text items of textString
set AppleScript's text item delimiters to ""
if (count of textItems) > 1 then
set textItem to item 2 of textItems
set AppleScript's text item delimiters to "\""
set textValue to text items of textItem
set AppleScript's text item delimiters to ""
if (count of textValue) > 1 then
set valueString to trimCharacters((item 2 of textValue), ";")
set valueString to trimCharacters(valueString, "\"")
return valueString as Unicode text
end if
end if
end if
return ""
end parseValue
on parseJson(jsonString, jsonElement)
repeat with delimiter1 in {"\":\"", "\": \""}
set AppleScript's text item delimiters to "\"" & jsonElement & delimiter1
set jsonItems to text items of jsonString
set AppleScript's text item delimiters to ""
if (count of jsonItems) > 1 then
set jsonValue to item 2 of jsonItems
repeat with delimiter2 in {"\"}", "\","}
set AppleScript's text item delimiters to delimiter2
set jsonValues to text items of jsonValue
set AppleScript's text item delimiters to ""
if (count of jsonValues) > 1 then
return decodeHTML(decodeURL(item 1 of jsonValues as Unicode text))
end if
end repeat
end if
end repeat
return ""
end parseJson
on trimCharacters(textString, trimCharacter)
repeat until textString does not start with trimCharacter
set textString to text 2 thru -1 of textString
end repeat
repeat until textString does not end with trimCharacter
set textString to text 1 thru -2 of textString
end repeat
return textString
end trimCharacters
on replaceCharacters(textString, searchString, replacementString)
set AppleScript's text item delimiters to the searchString
set the itemList to every text item of textString
set AppleScript's text item delimiters to the replacementString
set textString to the itemList as string
set AppleScript's text item delimiters to ""
return textString
end replaceCharacters
on encodeText(textString, encode_URL_A, encode_URL_B)
set the standardCharacters to "abcdefghijklmnopqrstuvwxyz0123456789"
set the URL_A_chars to "$+!'/?;&@=#%><{}[]\"~`^\\|*"
set the URL_B_chars to ".-_:"
set the acceptableCharacters to the standardCharacters
if encode_URL_A is false then set the acceptableCharacters to the acceptableCharacters & the URL_A_chars
if encode_URL_B is false then set the acceptableCharacters to the acceptableCharacters & the URL_B_chars
set the encodedText to ""
repeat with charString in textString
if charString is in the acceptableCharacters then
set the encodedText to (the encodedText & charString) as string
else
set the encodedText to (the encodedText & encodeCharacter(charString)) as string
end if
end repeat
return the encodedText
end encodeText
on encodeCharacter(charString)
set the ASCII_num to (the ASCII number charString)
set the hex_list to {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"}
set x to item ((ASCII_num div 16) + 1) of the hex_list
set y to item ((ASCII_num mod 16) + 1) of the hex_list
return ("%" & x & y) as string
end encodeCharacter
on decodeCharacters(charString)
copy charString to {indentifying_char, multiplier_char, remainder_char}
set the hexList to "123456789ABCDEF"
if the multiplier_char is in "ABCDEF" then
set the multiplier_amt to the offset of the multiplier_char in the hexList
else
set the multiplier_amt to the multiplier_char as integer
end if
if the remainder_char is in "ABCDEF" then
set the remainder_amt to the offset of the remainder_char in the hexList
else
set the remainder_amt to the remainder_char as integer
end if
set the ASCII_num to (multiplier_amt * 16) + remainder_amt
return (ASCII character ASCII_num)
end decodeCharacters
on decodeURL(textString)
set flag_A to false
set flag_B to false
set temp_char to ""
set the characterList to {}
repeat with charString in textString
set charString to contents of charString
if charString is "%" then
set flag_A to true
else if flag_A is true then
set the temp_char to charString
set flag_A to false
set flag_B to true
else if flag_B is true then
set the end of characterList to my decodeCharacters(("%" & temp_char & charString) as string)
set the temp_char to ""
set flag_A to false
set flag_B to false
else
set the end of characterList to charString
end if
end repeat
return characterList as string
end decodeURL
on decodeHTML(textString)
repeat with entities in {{"\\u0026", "&"}, ¬
{" ", " "}, {"!", "!"}, {""", "\""}, {"#", "#"}, {"$", "$"}, ¬
{"%", "%"}, {"&", "&"}, {"'", "'"}, {"(", "("}, {")", ")"}, ¬
{"*", "*"}, {"+", "+"}, {",", ","}, {"-", "-"}, {".", "."}, ¬
{"/", "/"}, {":", ":"}, {";", ";"}, {"<", "<"}, {"=", "="}, ¬
{">", ">"}, {"?", "?"}, {"@", "@"}, {"[", "["}, {"\", "\\"}, ¬
{"]", "]"}, {"^", "^"}, {"_", "_"}, {"`", "`"}, {"{", "{"}, ¬
{"|", "|"}, {"}", "}"}, {"~", "~"}, {" ", " "}, {"¡", "¡"}, ¬
{"¢", "¢"}, {"£", "£"}, {"¤", "¤"}, {"¥", "¥"}, {"¦", "¦"}, ¬
{"§", "§"}, {"¨", "¨"}, {"©", "©"}, {"ª", "ª"}, {"«", "«"}, ¬
{"®", "®"}, {"¯", "¯"}, {"°", "°"}, {"±", "±"}, {"²", "²"}, ¬
{"³", "³"}, {"´", "´"}, {"µ", "µ"}, {"¶", "¶"}, {"·", "·"}, ¬
{"¸", "¸"}, {"¹", "¹"}, {"º", "º"}, {"»", "»"}, {"¼", "¼"}, ¬
{"½", "½"}, {"¾", "¾"}, {"¿", "¿"}, {"À", "À"}, {"Á", "Á"}, ¬
{"Â", "Â"}, {"Ã", "Ã"}, {"Ä", "Ä"}, {"Å", "Å"}, {"Æ", "Æ"}, ¬
{"Ç", "Ç"}, {"È", "È"}, {"É", "É"}, {"Ê", "Ê"}, {"Ë", "Ë"}, ¬
{"Ì", "Ì"}, {"Í", "Í"}, {"Î", "Î"}, {"Ï", "Ï"}, {"Ð", "Ð"}, ¬
{"Ñ", "Ñ"}, {"Ò", "Ò"}, {"Ó", "Ó"}, {"Ô", "Ô"}, {"Õ", "Õ"}, ¬
{"Ö", "Ö"}, {"×", "×"}, {"Ø", "Ø"}, {"Ù", "Ù"}, {"Ú", "Ú"}, ¬
{"Û", "Û"}, {"Ü", "Ü"}, {"Ý", "Ý"}, {"Þ", "Þ"}, {"ß", "ß"}, ¬
{"à", "à"}, {"á", "á"}, {"â", "â"}, {"ã", "ã"}, {"ä", "ä"}, ¬
{"å", "å"}, {"æ", "æ"}, {"ç", "ç"}, {"è", "è"}, {"é", "é"}, ¬
{"ê", "ê"}, {"ë", "ë"}, {"ì", "ì"}, {"í", "í"}, {"î", "î"}, ¬
{"ï", "ï"}, {"ð", "ð"}, {"ñ", "ñ"}, {"ò", "ò"}, {"ó", "ó"}, ¬
{"ô", "ô"}, {"õ", "õ"}, {"ö", "ö"}, {"÷", "÷"}, {"ø", "ø"}, ¬
{"ù", "ù"}, {"ú", "ú"}, {"û", "û"}, {"ü", "ü"}, {"ý", "ý"}, ¬
{"þ", "þ"}, {"ÿ", "ÿ"}, {"Œ", "Œ"}, {"œ", "œ"}, {"Š", "Š"}, ¬
{"š", "š"}, {"Ÿ", "Ÿ"}, {"ƒ", "ƒ"}, {"–", "–"}, {"—", "—"}, ¬
{"‘", "‘"}, {"’", "’"}, {"‚", "‚"}, {"“", "“"}, {"”", "”"}, ¬
{"„", "„"}, {"†", "†"}, {"‡", "‡"}, {"•", "•"}, {"…", "…"}, ¬
{"‰", "‰"}, {"€", "€"}, {"™", "™"}}
set textString to replaceCharacters(textString, item 1 of entities, item 2 of entities)
end repeat
return textString as string
end decodeHTML
The script is still a work in progress, so any feedback is gladly welcome. You can download the Applescript at Translate.scpt










0 comments:
Post a Comment