ExcelスプレッドシートからAndroidおよびiOSのローカライズファイルを自動的に作成する

画像







こんにちは、私の名前はアレクサンダーで、Androidアプリケーション開発者です。 11のインターフェース言語と600行を超えるプロジェクトに参加しました。 顧客側にはプログラマーがいなかったため、すべてをExcelスプレッドシートに保存しました。 彼らがその中の何かを変更したとき、彼らは「私たちはそれぞれ黄色と黄色の変更でセルを強調表示し、AndroidとiOSのアプリケーションをそれぞれ更新する」という言葉でこの表を送りました。 その後、2人の開発者が数時間を失い、手動で変更を加えました。 そして、誰かがどこかで何かを忘れていたり、間違えたり、それを終わらせなかったり、プラットフォーム間に矛盾があったり、顧客が緊張したり、開発者がびっくりしたりすることが判明しました。 この状況は根本的に私には適さず、Excelからの行のアンロードを自動化する方法を探し始めました。 その結果、すばらしいVBScriptコードが完成しましたが、今でも使用しています。 次に、このスクリプトを紹介します。 カットの下に、いくつかの写真とスクリプトコードがあります。







そのため、まずテーブル自体を見て、問題の規模を評価します。







画像







そこに彼女は美人だ! ご覧のとおり、いくつかのサービス列、グローバル回線名、およびそれらの翻訳があります。 さらに、一部の行は英語とドイツ語でのみ表示されます。これは、アプリケーションのバージョン2.0では、顧客が現在のところ2つの言語のみを残し、残りを後で追加することを決定したためです。 または多分彼は翻訳者のためにお金を同情します。 しかし、これは彼のビジネスですが、これを考慮に入れる必要があります。 つまり、スクリプトは空のセルをスキップし、そのような言語の空の行を作成しないでください。 さらに、セルF5の「%s」などの書式設定文字も考慮する必要があります。 iOSでAndroidが得意とするものは「%@」に置き換える必要があるため、これらのユーザーと協力する必要があります。 途中で他のニュアンスについて説明します。







衰弱せず、猫を尻尾で引っ張らないように、今すぐスクリプト全体を投稿します。







栄光に満ちたVBScript
option explicit ' Start it with: cscript ConvertExcelToTXTandXML.vbs If UCASE(right(wscript.fullname,11)) <> "CSCRIPT.EXE" Then Msgbox "Please enter: cscript ConvertExcelToTXTandXML.vbs <filename>.xlsx" WScript.Quit 255 End If ' The column of the key is 4 Const KeyColumn = 4 ' Names of destination files to create Const outFileiOS="\Localizable.strings" Const outFileiOSLocale="\InfoPlist.strings" Const outFileAndroid="\stringsToFormat.xml" Const NsCameraUsageDescription = "NsCameraUsageDescription" Const NSLocationAlwaysAndWhenInUseUsageDescription = "NSLocationAlwaysAndWhenInUseUsageDescription" Const NSLocationAlwaysUsageDescription = "NSLocationAlwaysUsageDescription" Const NSLocationWhenInUseUsageDescription = "NSLocationWhenInUseUsageDescription" Const NSPhotoLibraryAddUsageDescription = "NSPhotoLibraryAddUsageDescription" Const NSPhotoLibraryUsageDescription = "NSPhotoLibraryUsageDescription" Dim oExcel Dim oTranslations Dim objOutputFileiOS Dim objOutputFileiOSLocale Dim objFSO Dim objFSOandroid Dim objFSOios Dim myArgs Dim myParameter Dim sName Dim CompletePath Dim WorkingDir Dim WorkingDirAndroid Dim WorkingDirIos Dim LanguageColumnIndex Dim UsedRows Dim nCounter Dim xmlDoc Dim objIntro Dim objRoot Dim objHdr Dim objHdrAtt Dim theText Dim AndroidString Dim iOSString ' **************************************** ' MAKE PRETTY XML ' **************************************** Const strOutputFile = "\strings.xml" ' **************************************** Dim objInputFile, objOutputFile, strXML Dim objXML : Set objXML = WScript.CreateObject("Msxml2.DOMDocument") Dim objXSL : Set objXSL = WScript.CreateObject("Msxml2.DOMDocument") ' Create interface to Excel Set oExcel = CreateObject("Excel.application") ' Create the file interface Set objFSO=CreateObject("Scripting.FileSystemObject") ' Get the commandline parameter Set myArgs = WScript.Arguments.Unnamed If myArgs.count > 0 Then If (not objFSO.FileExists(myArgs.item(0))) Then Wscript.Echo "Error: '" & myArgs.item(0) & "' not found" WScript.Quit 255 End If Set myParameter = objFSO.GetFile(myArgs.item(0)) sName = myParameter.Name CompletePath = myParameter.Path WorkingDir = myParameter.Path WorkingDir = Left(WorkingDir, Len(WorkingDir)-Len(sName)) WorkingDirAndroid = "res\" WorkingDirIos = "ios\" If Not objFSO.FolderExists(WorkingDir & WorkingDirAndroid) Then ' Create folder if not exists' objFSO.CreateFolder(WorkingDir & WorkingDirAndroid) End If If Not objFSO.FolderExists(WorkingDir & WorkingDirIos) Then ' Create folder if not exists' objFSO.CreateFolder(WorkingDir & WorkingDirIos) End If Else Wscript.Echo "Error: A filename is needed" WScript.Quit 255 End If ' Source file Set oTranslations = oExcel.Workbooks.Open(CompletePath) ' Get the maximum number of rows in the sheet UsedRows = oTranslations.Sheets(1).UsedRange.Rows.Count ' In this column start the start the languages' LanguageColumnIndex = 6 ' stop the processing when the cell is empty --> end of languages while oTranslations.Sheets(1).Cells(3, LanguageColumnIndex) <> "" WScript.stdout.Write "Create files for: " WScript.stdout.Write oTranslations.Sheets(1).Cells(3, LanguageColumnIndex) WScript.stdout.Write " " objFSOandroid = oTranslations.Sheets(1).Cells(3, LanguageColumnIndex) If objFSOandroid = "values" Then objFSOios = "en" & ".lproj" ElseIf objFSOandroid = "values-ru" Then objFSOios = "ru-RU" & ".lproj" Else objFSOios = Right(objFSOandroid,2) & ".lproj" End If WScript.stdout.Write "; iOs folder: " WScript.stdout.Write objFSOios If Not objFSO.FolderExists(WorkingDir & WorkingDirAndroid & objFSOandroid) Then ' Create folder if not exists' objFSO.CreateFolder(WorkingDir & WorkingDirAndroid & objFSOandroid) End If If Not objFSO.FolderExists(WorkingDir & WorkingDirIos & objFSOios) Then ' Create folder if not exists' objFSO.CreateFolder(WorkingDir & WorkingDirIos & objFSOios) End If ' Create the destination files Set objOutputFileiOS = CreateObject("ADODB.Stream") objOutputFileiOS.CharSet = "utf-8" objOutputFileiOS.Open Set objOutputFileiOSLocale = CreateObject("ADODB.Stream") objOutputFileiOSLocale.CharSet = "utf-8" objOutputFileiOSLocale.Open Set xmlDoc = CreateObject("Msxml2.DOMDocument") ' NOTE: chr(34) is " ' NOTE: vbCrLf is <CR><LF> ' Create the XML header Set objIntro = xmlDoc.createProcessingInstruction("xml","version='1.0' encoding='UTF-8' standalone='yes'") xmlDoc.insertBefore objIntro,xmlDoc.childNodes(0) Set objRoot = xmlDoc.createElement("resources") xmlDoc.appendChild objRoot ' keys start in row 3!!! For nCounter = 3 To UsedRows WScript.stdout.Write "." If oTranslations.Sheets(1).Cells(nCounter, KeyColumn).Value <> "" Then ' Write to iOS file If Not oTranslations.Sheets(1).Cells(nCounter, LanguageColumnIndex).Value = "" Then objOutputFileiOS.WriteText chr(34) objOutputFileiOS.WriteText oTranslations.Sheets(1).Cells(nCounter, KeyColumn).Value objOutputFileiOS.WriteText chr(34) objOutputFileiOS.WriteText " = " objOutputFileiOS.WriteText chr(34) iOSString = Replace(oTranslations.Sheets(1).Cells(nCounter, LanguageColumnIndex).Value, "%s", "%@") iOSString = Replace(iOSString, "'", "\'") iOSString = Replace(iOSString, chr(34), "\" & chr(34)) objOutputFileiOS.WriteText iOSString objOutputFileiOS.WriteText chr(34) objOutputFileiOS.WriteText ";" & vbCrLf If ( (oTranslations.Sheets(1).Cells(nCounter, KeyColumn).Value = NsCameraUsageDescription) _ or (oTranslations.Sheets(1).Cells(nCounter, KeyColumn).Value = NSLocationAlwaysAndWhenInUseUsageDescription) _ or (oTranslations.Sheets(1).Cells(nCounter, KeyColumn).Value = NSLocationAlwaysUsageDescription) _ or (oTranslations.Sheets(1).Cells(nCounter, KeyColumn).Value = NSLocationWhenInUseUsageDescription) _ or (oTranslations.Sheets(1).Cells(nCounter, KeyColumn).Value = NSPhotoLibraryAddUsageDescription) _ or (oTranslations.Sheets(1).Cells(nCounter, KeyColumn).Value = NSPhotoLibraryUsageDescription) _ ) Then objOutputFileiOSLocale.WriteText chr(34) objOutputFileiOSLocale.WriteText oTranslations.Sheets(1).Cells(nCounter, KeyColumn).Value objOutputFileiOSLocale.WriteText chr(34) objOutputFileiOSLocale.WriteText " = " objOutputFileiOSLocale.WriteText chr(34) objOutputFileiOSLocale.WriteText iOSString objOutputFileiOSLocale.WriteText chr(34) objOutputFileiOSLocale.WriteText ";" & vbCrLf End If End If ' Write to Android file Set objHdr = xmlDoc.createElement("string") Set objHdrAtt = xmlDoc.createAttribute("name") objHdrAtt.text = oTranslations.Sheets(1).Cells(nCounter, KeyColumn).Value AndroidString =Replace (oTranslations.Sheets(1).Cells(nCounter, LanguageColumnIndex).Value, "'", "\'") AndroidString =Replace (oTranslations.Sheets(1).Cells(nCounter, LanguageColumnIndex).Value, Chr(10), "\n") If Not AndroidString = "" Then Set theText=xmlDoc.createTextNode(AndroidString) objHdr.setAttributeNode objHdrAtt objHdr.appendChild theText objRoot.appendChild objHdr End If End If Next ' Save the files xmlDoc.Save WorkingDir & WorkingDirAndroid & objFSOandroid & outFileAndroid ' **************************************** ' Put whitespace between tags. (Required for XSL transformation.) ' **************************************** Set objInputFile = objFSO.OpenTextFile(WorkingDir & WorkingDirAndroid & objFSOandroid & outFileAndroid,1,False,-2) Set objOutputFile = objFSO.CreateTextFile(WorkingDir & WorkingDirAndroid & objFSOandroid & strOutputFile,True,False) strXML = objInputFile.ReadAll strXML = Replace(strXML,"><",">" & vbCrLf & "<") objOutputFile.Write strXML objInputFile.Close objFSO.DeleteFile(WorkingDir & WorkingDirAndroid & objFSOandroid & outFileAndroid) objOutputFile.Close ' **************************************** ' Create an XSL stylesheet for transformation. ' **************************************** Dim strStylesheet : strStylesheet = _ "<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"">" & _ "<xsl:output method=""xml"" indent=""yes""/>" & _ "<xsl:template match=""/"">" & _ "<xsl:copy-of select="".""/>" & _ "</xsl:template>" & _ "</xsl:stylesheet>" ' **************************************** ' Transform the XML. ' **************************************** objXSL.loadXML strStylesheet objXML.load WorkingDir & WorkingDirAndroid & objFSOandroid & strOutputFile objXML.transformNode objXSL objXML.save WorkingDir & WorkingDirAndroid & objFSOandroid & strOutputFile ' **************************************** ' End transformation. ' **************************************** objOutputFileiOSLocale.SaveToFile WorkingDir & WorkingDirIos & objFSOios & outFileiOSLocale, 2 objOutputFileiOS.SaveToFile WorkingDir & WorkingDirIos & objFSOios & outFileiOS, 2 LanguageColumnIndex = LanguageColumnIndex + 1 WScript.stdout.Write vbCrLf wend oTranslations.Close oExcel.Quit WScript.Echo "With success done" WScript.Quit(0)
      
      





今こそ、ニュアンスを体験する時です。







このアプリケーションには、いくつかのユーザー権限が必要です。 iOSでは、これらの許可を要求するための行はLocalizable.stringsではなくInfoPlist.stringsに通常格納されているため、スクリプトの最初でInfoPlistに配置される行の名前を定義します。







 Const NsCameraUsageDescription = "NsCameraUsageDescription" Const NSLocationAlwaysAndWhenInUseUsageDescription = "NSLocationAlwaysAndWhenInUseUsageDescription" Const NSLocationAlwaysUsageDescription = "NSLocationAlwaysUsageDescription" Const NSLocationWhenInUseUsageDescription = "NSLocationWhenInUseUsageDescription" Const NSPhotoLibraryAddUsageDescription = "NSPhotoLibraryAddUsageDescription" Const NSPhotoLibraryUsageDescription = "NSPhotoLibraryUsageDescription"
      
      





次に注目すべきフラグメントは、すべてのファイルが保存されるフォルダーの名前です。 iOSでは、すべてのフォルダーに「en.lproj」、「de.lproj」などの2文字の言語指定が付いています。 ロシア語以外のすべてはここに「ru-RU」です。 また、テーブル自体の列はAndroid表記です。 したがって、parsim:







 If objFSOandroid = "values" Then objFSOios = "en" & ".lproj" ElseIf objFSOandroid = "values-ru" Then objFSOios = "ru-RU" & ".lproj" Else objFSOios = Right(objFSOandroid,2) & ".lproj" End If
      
      





そして最後のタスク、キャラクターの置き換えとエスケープ。 iOSの場合、私が言ったように、 %s%@に変更し、引用符とアポストロフィをエスケープします。







 iOSString = Replace(oTranslations.Sheets(1).Cells(nCounter, LanguageColumnIndex).Value, "%s", "%@") iOSString = Replace(iOSString, "'", "\'") iOSString = Replace(iOSString, chr(34), "\" & chr(34))
      
      





Androidでは、アポストロフィをエスケープし、いわゆる改行文字( Chr(10) )を通常の改行文字\ nに置き換えます。 そして、これには理由があります。 セルの1つには、かなり大きなテキストがあり、顧客がMS Wordでコンパイルし、テクニカルコピーペーストを使用してExcelセルに配置しました。 そして、試行錯誤による適切な置き換えを見つけることができませんでしたが、iOSでは必要な段落にテキストが表示され、Androidでは1つの段落にマージされました。







おわりに



おそらく既に推測したように、スクリプトはWindowsコマンドラインで実行されます。 簡単にするために、スクリプトと.xlsxファイルを1つのフォルダーに入れ、コマンドラインに移動してコマンドを記述します。







cscript ConvertExcelToTXTandXML.vbs <filename>.xlsx









次に、Enterキーを押して、プログラムの各ステップのコマンドウィンドウに表示されるドットの形で、スクリプトの美しい視覚化をお楽しみください。 スクリプトの巨大な作業の結果、「ios」と「res」の2つのフォルダーが作成され、その内容はそれぞれiOSプロジェクトとAndroidプロジェクトにコピーされます。







以上です。 このスクリプトが誰かにとって有用であり、多くの時間を節約することを願っています。








All Articles