Skip to content

Commit

Permalink
Allow tables to be inset.
Browse files Browse the repository at this point in the history
+ Organize config keys
+ Change error handling
  • Loading branch information
Roman Gille committed Oct 31, 2022
1 parent 4961ba3 commit 76e189c
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 27 deletions.
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,30 @@ This is a python script that downloads localization strings and CI color informa

## Installation

This uses the [pip](https://packaging.python.org/en/latest/key_projects/#pip) package manager for Python packages ([see guide](https://packaging.python.org/en/latest/tutorials/installing-packages/)). It depends on the [pyexcel-ods](https://pypi.org/project/pyexcel-ods/) package whick will be installed alongsite automatically when you run:
This uses the [pip](https://packaging.python.org/en/latest/key_projects/#pip) package manager for Python packages ([see guide](https://packaging.python.org/en/latest/tutorials/installing-packages/)). It depends on the [pyexcel-ods](https://pypi.org/project/pyexcel-ods/) package which will be installed alongsite automatically when you run:

pip install localization-sync

Hint: It could be that you need to use `pip3` commant instead uf `pip`.
Hint: It could be that you need to use `pip3` command instead of `pip`.

## Prerequisites

### 1. Create a Google Sheet

Create a Google Sheet document with sheets like [these](https://docs.google.com/spreadsheets/d/1672QPWDsxBtaX5hc5QgZhqBwLADMnPVEv7-wLB3g-ug):

![Example of a L10n table](Resources/sheet_l10n.png)
![Example of a colors table](Resources/sheet_colors.png)

Publish the sheeet to the web by pressing __File -> Publish to the web__. Select __Whole Document__ and __Website__. This gives the script access to the public JSON API of Google Docs.
Mind to __not__ add extra columns or rows at the top/left of your tables. I you need to do so, use `keyRow`/`keyColumn` parameters in config to inset the parsing of the table.

### 2. Publish

Publish the sheeet to the web by pressing __File -> Publish to the web__. Select __Whole Document__ and __Website__. This enables the script do export the contents of the sheet as ODS file.

_Note_: We are using the export instead of the JSON API. Because this way there is no need for creating an API Key and using OAuth on the client (your) side.

### 3. Get the ID

Find the ID of your document by copying it from your browsers address bar.

Expand Down
95 changes: 71 additions & 24 deletions Sources/data_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


from array import array
import enum
import json
import os
import re
Expand Down Expand Up @@ -49,6 +51,18 @@ def link(uri, label=None):
print("Could not import "+ link("https://pypi.org/project/pyexcel-ods/", "pyexcel-ods") +".\nPlease run: pip install pyexcel-ods")
exit()

CONF_L10N = "l10n"
CONF_COLORS = "colors"
CONF_SHEET_ID = "sheetId"
CONF_OS = "os"
CONF_SHEET_NAME = "sheetName"
CONF_BASE_LANG = "baseLanguage"
CONF_OUT_FOLDER = "outputFolder"
CONF_FILE_NAME = "fileName"
CONF_KEY_PREFIX = "keyPrefix"
CONF_KEY_ROW = "keyRow"
CONF_KEY_COL = "keyColumn"

placeholderPattern = re.compile(r'{String([0-9]*)}|{Number([0-9]*)}')
scriptRunPath = os.getcwd()
scriptFileName = os.path.basename(__file__)
Expand Down Expand Up @@ -76,13 +90,41 @@ def loadDocument(spreadsheedId):
shutil.rmtree(tempPath)
return content

def writeLocalizations(document, configuration):
rows = document[configuration["sheetName"]]
# TRims stuff
def trim(rows: list, firstRow: int, firstColumn: int) -> list:
trimmedRows = []
for rowIndex, row in enumerate(rows):
if rowIndex < firstRow:
continue
trimmedRow = []
for colIndex, col in enumerate(row):
if colIndex < firstColumn:
continue
trimmedRow.append(col)
trimmedRows.append(trimmedRow)
return trimmedRows

def writeLocalizations(document: dict, configuration: dict):
# Set default values.
if (CONF_BASE_LANG not in configuration): configuration[CONF_BASE_LANG] = "en"
if (CONF_KEY_PREFIX not in configuration): configuration[CONF_KEY_PREFIX] = ""
keyRow: int = 0 if (CONF_KEY_ROW not in configuration) else int(configuration[CONF_KEY_ROW])
keyColumn: int = 0 if (CONF_KEY_COL not in configuration) else int(configuration[CONF_KEY_COL])

rows = trim(
rows=document[configuration[CONF_SHEET_NAME]],
firstRow=keyRow,
firstColumn=keyColumn
)
languageCount = len(rows[0]) - 1
print("Found %i languages." % languageCount)

for languageColumn in range(1, 1 + languageCount):
languageKey = rows[0][languageColumn].replace(" ", "")
languageKey = rows[0][languageColumn].strip().lower()
if " " in languageKey:
print("\""+ languageKey +"\" is not a valid language key. Skipped processing. Please check your config!")
continue
print("Processing \""+ languageKey +"\" at column "+ str(languageColumn + keyColumn) +".")

if configuration["os"] == "iOS":
buildLocalizationIOS(rows, languageColumn, languageKey, configuration)
Expand All @@ -93,11 +135,9 @@ def writeLocalizations(document, configuration):
def buildLocalizationIOS(rows, column, languageKey, configuration):

# Prepare paths.
baseLanguage = "en" if ("baseLanguage" not in configuration) else configuration["baseLanguage"]
keyPrefix = "" if ("keyPrefix" not in configuration) else configuration["keyPrefix"]
languageFolderName = "Base" if (languageKey == baseLanguage) else languageKey
folderPath = configuration["outputFolder"] + "/" + languageFolderName + ".lproj"
fileName = configuration["fileName"] + ".strings"
languageFolderName = "Base" if (languageKey == configuration[CONF_BASE_LANG]) else languageKey
folderPath = configuration[CONF_OUT_FOLDER] + "/" + languageFolderName + ".lproj"
fileName = configuration[CONF_FILE_NAME] + ".strings"
filePath = folderPath + "/" + fileName

# Prepare file.
Expand All @@ -116,11 +156,11 @@ def buildLocalizationIOS(rows, column, languageKey, configuration):
continue

# Skip empty translations...
if not row[column]:
if not (column < len(row)) or (not row[column]):
continue

translation = placeholderPattern.sub("%@", row[column])
line = "\"%s\" = \"%s\";" % (keyPrefix + key, translation)
line = "\"%s\" = \"%s\";" % (configuration[CONF_KEY_PREFIX] + key, translation)
# Check if the line is commented.
if key.startswith(l10nCommentIdentifier):
l10nWriteComment(line, outputFile)
Expand All @@ -135,11 +175,10 @@ def buildLocalizationIOS(rows, column, languageKey, configuration):
def buildLocalizationAndroid(rows, column, languageKey, configuration):

# Prepare paths.
isBaseLanguage = (configuration["baseLanguage"] == languageKey)
keyPrefix = "" if ("keyPrefix" not in configuration) else configuration["keyPrefix"]
isBaseLanguage = (configuration[CONF_BASE_LANG] == languageKey)
languageFolderName = "values" if isBaseLanguage else "values-" + languageKey
folderPath = configuration["outputFolder"] + "/" + languageFolderName
fileName = configuration["fileName"] + ".xml"
folderPath = configuration[CONF_OUT_FOLDER] + "/" + languageFolderName
fileName = configuration[CONF_FILE_NAME] + ".xml"
filePath = folderPath + "/" + fileName

strings = []
Expand All @@ -153,10 +192,15 @@ def buildLocalizationAndroid(rows, column, languageKey, configuration):
if key.startswith(l10nSectionTitleIdentifier):
strings.append({key: ""})
continue

# Skip empty translations...
if not (column < len(row)) or (not row[column]):
continue

# Skip comments.
if key.startswith(l10nCommentIdentifier):
continue
strings.append({keyPrefix + key: placeholderPattern.sub("%s", row[column])})
strings.append({configuration[CONF_KEY_PREFIX] + key: placeholderPattern.sub("%s", row[column])})

outputFile = startFile(folderPath, filePath, fileName)
outputFile.write(buildResourceXML(strings, "string"))
Expand All @@ -165,11 +209,11 @@ def buildLocalizationAndroid(rows, column, languageKey, configuration):

def writeColors(document, configuration):

rows = document[configuration["sheetName"]]
rows = document[configuration[CONF_SHEET_NAME]]
isAndroid = (configuration["os"] == "Android")
fileExtension = ".xml" if isAndroid else ".json"
folderPath = configuration["outputFolder"]
fileName = configuration["fileName"] + fileExtension
folderPath = configuration[CONF_OUT_FOLDER]
fileName = configuration[CONF_FILE_NAME] + fileExtension
filePath = folderPath + "/" + fileName

colors = []
Expand Down Expand Up @@ -243,18 +287,21 @@ def xmlWriteSectionComment(sectionTitle):

def run(config):

sheetId = config["sheetId"]
sheetId = config[CONF_SHEET_ID]
try:
document = loadDocument(sheetId)

for l10nConfig in config["l10n"]:
writeLocalizations(document, l10nConfig)
if CONF_L10N in config:
for l10nConfig in config[CONF_L10N]:
writeLocalizations(document, l10nConfig)

for colorConfig in config["colors"]:
writeColors(document, colorConfig)
if CONF_COLORS in config:
for colorConfig in config[CONF_COLORS]:
writeColors(document, colorConfig)

except Exception as exc:
print("Cannot process sheet - Error: "+ exc)
print("Cannot process sheet - Error:")
print(exc)

def main():
# Parse config file and run tasks.
Expand Down

0 comments on commit 76e189c

Please sign in to comment.