إنشاء ملفات تعريب Android و iOS تلقائيًا من جدول بيانات Excel

صورة


مرحباً ، اسمي ألكساندر وأنا مطور تطبيقات أندرويد. بمجرد أن حصلت على مشروع يحتوي على 11 لغة واجهة وأكثر من 600 سطر. لم يكن هناك مبرمجون من جانب العميل ، لذا قاموا بتخزين كل شيء في جدول بيانات Excel. عندما غيّروا شيئًا ما فيه ، أرسلوا هذا الجدول إلينا بعبارة "لقد أبرزنا الخلايا مع تغييرات في اللون الأصفر ، وقم بتحديث تطبيقات Android و iOS ، على التوالي." بعد ذلك ، فقد اثنين من المطورين بضع ساعات ، وإجراء تغييرات يدويا. ثم اتضح أن شخصًا ما قد نسي شيئًا ما في مكان ما ، أو ارتكب خطأ أو لم ينته ، فقد كانت هناك تباينات بين المنصات ، وكان العميل متوترًا ، وكان المطورون يخافون. لم يناسبني هذا الموقف ، لقد بدأت في البحث عن طرق لأتمتة تفريغ الصفوف من Excel. كانت النتيجة رمز VBScript رائعًا ، والذي ما زلنا نستمتع باستخدامه. الآن سوف أقدم هذا السيناريو لك. تحت القص ، وعدد معين من الصور ورمز البرنامج النصي.


لذا ، أولاً ، ألقِ نظرة على الجدول نفسه وقيّم حجم المشكلة:


صورة


ها هي ، الجمال! كما نرى ، هناك العديد من أعمدة الخدمة وأسماء الخطوط العامة وترجماتها. علاوة على ذلك ، يتم تقديم بعض الأسطر باللغة الإنجليزية والألمانية فقط ، لأنه في الإصدار 2.0 من التطبيق ، قرر العميل ترك لغتين فقط في الوقت الحالي وإضافة الباقي لاحقًا. أو ربما يشفق على المال للمترجمين. ولكن هذا من أعماله ، لكن علينا أن نأخذ ذلك في الاعتبار. بمعنى ، يجب على البرنامج النصي تخطي الخلايا الفارغة وعدم إنشاء خطوط فارغة لمثل هذه اللغة. بالإضافة إلى ذلك ، يجب مراعاة أحرف التنسيق مثل "٪ s" في الخلية F5. سيتعين عليهم العمل ، لأن ما يجب أن يكون عليه Android في iOS يجب استبداله بـ "٪ @". سأخبرك عن الفروق الدقيقة الأخرى على طول الطريق.


لكي لا أضع القطة ولا تسحبها من الذيل ، سأقوم بنشر النص بأكمله الآن:


فبسكريبت في كل مجدها
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". كل شيء ما عدا الروسية ، وهنا "رو رو". وفي الجدول نفسه ، توجد الأعمدة بترميز 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 . وهناك سبب لذلك. في إحدى الخلايا ، يوجد نص كبير نوعًا ما ، يتم تجميعه بواسطة العميل في برنامج MS Word ووضعه في خلية Excel باستخدام لصق النسخ التقني. وعلى الرغم من أننا لم نعثر على البديل الصحيح عن طريق التجربة والخطأ ، فقد تم عرض النص في نظام التشغيل iOS في الفقرات الضرورية ، وتم دمجه في Android في فقرة واحدة.


استنتاج


كما قد تكون خمنت بالفعل ، يتم تشغيل البرنامج النصي في سطر أوامر Windows. للبساطة ، نضع البرنامج النصي وملف .xlsx في مجلد واحد ، وانتقل إلى سطر الأوامر هناك واكتب الأمر:


cscript ConvertExcelToTXTandXML.vbs <filename>.xlsx


بعد ذلك ، اضغط على Enter والتمتع بتصور جميل للبرنامج النصي في شكل نقاط تظهر في نافذة الأوامر لكل خطوة من خطوات البرنامج. نتيجة العمل الضخم للبرنامج النصي الخاص بنا هي مجلدين ، "ios" و "res" ، تبقى محتوياتهما لنسخها إلى مشروع iOS و Android ، على التوالي.


هذا كل شيء. آمل أن يكون هذا البرنامج مفيدًا لشخص ما ويوفر الكثير من الوقت.

Source: https://habr.com/ru/post/ar446100/


All Articles