Python script to create Android/iOS strings from a .csv My script takes a CSV file of strings and then creates an XML file for Android and a .strings file to be used for iOS. It separates each locale meaning that a file will be created for each language.

This has come in handy so far, making localising mobile apps easier. However, I am always seeking feedback so let me know what you think.

Input

The .csv is provided in the format: key, language1, language2 


key,en,ru
welcome_message,hello,здравствуйте
thank_you_message,thank you,спасибо
goodbye_message,goodbye,До свидания



Output

XML - Android

en_strings.xml



&lt;?xml version="1.0" ?&gt;
&lt;resources&gt;
    &lt;string name="welcome_message"&gt;hello&lt;/string&gt;
    &lt;string name="thank_you_message"&gt;thank you&lt;/string&gt;
    &lt;string name="goodbye_message"&gt;goodbye&lt;/string&gt;
&lt;/resources&gt;


ru_strings.xml

&lt;?xml version="1.0" ?&gt;
&lt;resources&gt;
    &lt;string name="welcome_message"&gt;здравствуйте&lt;/string&gt;
    &lt;string name="thank_you_message"&gt;спасибо&lt;/string&gt;
    &lt;string name="goodbye_message"&gt;До свидания&lt;/string&gt;
&lt;/resources&gt;


.Strings - iOS

en.strings

/*  */
"welcome_message" = "hello";

/*  */
"thank_you_message" = "thank you";

/*  */
"goodbye_message" = "goodbye";


ru.strings

/*  */
"welcome_message" = "здравствуйте";

/*  */
"thank_you_message" = "спасибо";

/*  */
"goodbye_message" = "До свидания";


At the moment I've just hardcoded the origin Strings.csv file and the user defines the target directory, this will be useful when integrating it into automatic builds etc.



# -*- coding: utf-8 -*-
# Script takes a csv and creates strings for Android (.xml) and iOS (.Strings).
# csv in the format [key, language1, langauge2 ......]
# usage - Python converter.py [FILEPATH]

import sys, os, getopt, csv, xml.etree.ElementTree as ET
from xml.dom import minidom

def prettify(elem):
    rough_string = ET.tostring(elem, 'utf-8')
    reparsed = minidom.parseString(rough_string)
    return reparsed.toprettyxml(indent="\t")

# Read in output directory
try:   
   sys.argv[1:] 
   fileDestination = sys.argv[1]
except IndexError:  
   print "Error: Please supply an output directory."
   print "Usage: converter.py [FILEPATH]"
   sys.exit()  

# Create directory if it doesn't exists
if not os.path.exists(fileDestination):
    os.makedirs(fileDestination)

# Read from csv
f = open('Strings.csv')
csv_f = csv.reader(f)

# Determine the number of languages from the csv
line1 = csv_f.next()
numberOfLocales =  len(line1)

# Create strings for each language
for x in range(1, numberOfLocales):
    #Returns to the start of the csv and ignores the first line
    f.seek(0)
    csv_f.next()
    rowIndex = 0

    # Android xml
    resources = ET.Element("resources")

    # Create iOS strings file
    iOSFile = open(fileDestination+"/"+line1[x]+".Strings", "w+")

    for row in csv_f:
        ++rowIndex
        try:
            # Write string to xml
            ET.SubElement(resources, "string", name=row[0]).text = row[x].decode('utf-8')
            # Write string to iOS .Strings
            iOSFile.write("/*  */\n")
            iOSFile.write('"'+row[0]+'"'+ ' = ' + '"'+row[x]+'"' + ";\n")
            iOSFile.write("\n")
        except IndexError:
            f.seek(0)
            print "There is a problem with the csv file at row {}".format(rowIndex+1) + " with the language {}".format(line1[x])
            r = list(csv_f)
            print r[rowIndex]
            sys.exit()
    # Write to Android file
    androidFile = open(fileDestination+"/"+line1[x]+"_strings.xml", "w+")
    androidFile.write(prettify(resources).encode('utf-8'))
The Python style for naming is snake_case for functions and variables, and PascalCase for classes. If you have constant variables (values don't change), they should be in UPPER_SNAKE_CASE.

You also shouldn't be importing multiple modules on one line, like you've done here:

import sys, os, getopt, csv, xml.etree.ElementTree as ET


These imports should be separated onto separate lines, as per PEP8, Python's official style guide.

These comments at the very top of your file:

# Script takes a csv and creates strings for Android (.xml) and iOS (.Strings).
# csv in the format [key, language1, langauge2 ......]
# usage - Python converter.py [FILEPATH]


Should be converted into a docstring, like this:

"""
Script takes a csv and creates strings for Android (.xml) and iOS (.Strings).
csv in the format [key, language1, langauge2 ......]
usage - Python converter.py [FILEPATH]
"""


This is not how you should be opening files.

f = open('Strings.csv')


Rather, you should use a with ... as ... context manager. By using a context manager, you can ensure that the file is properly closed. Here's how you'd do that:

with open("Strings.csv") as f:
    ...


Finally, the below line does nothing.

++rowIndex


It should be changed to row_index += 1, if I understand your intent correctly.