Exemple #1
0
    IEnumerator loadLanguage(Language language)
    {
        System.DateTime started  = System.DateTime.Now;
        string          filePath = Path.Combine(Application.streamingAssetsPath, "Languages/" + language.getFileName());

        languageString = "";
        if (filePath.Contains("://"))
        {
            WWW www = new WWW(filePath);
            yield return(www);

            languageString = www.text;
        }
        else
        {
            languageString = File.ReadAllText(filePath);
        }

        localizedText = SerializedNestedStrings.deserialize(languageString);

        System.TimeSpan timeElapsed = System.DateTime.Now - started;
        Debug.Log("Language " + language.getFileName() + " loaded in " + timeElapsed.TotalMilliseconds + "ms");
        PrefsHelper.setPreferredLanguage(language.getLanguageID());

        loadedLanguage = language;
        languageString = "";
    }
Exemple #2
0
    IEnumerator loadLanguage(Language language)
    {
        System.DateTime started  = System.DateTime.Now;
        string          filePath = Path.Combine(Application.streamingAssetsPath, "Languages/" + language.getFileName());

        languageString = "";
        if (filePath.Contains("://"))
        {
            WWW www = new WWW(filePath);
            yield return(www);

            languageString = www.text;
        }
        else
        {
            languageString = File.ReadAllText(filePath);
        }

        localizedText = SerializedNestedStrings.deserialize(languageString);

        System.TimeSpan timeElapsed = System.DateTime.Now - started;
        Debug.Log("Language " + language.getFileName() + " loaded in " + timeElapsed.TotalMilliseconds + "ms");
        PrefsHelper.setPreferredLanguage(language.getLanguageID());
        languageFontMetadata = localizedText.getSubData("meta.font");

        loadedLanguageIsComplete = false;
        loadedLanguage           = language;
        languageString           = "";
        loadedLanguageIsComplete = getLocalizedValue("generic.complete", "N").Equals("Y", System.StringComparison.OrdinalIgnoreCase);

        if (onLanguageChanged != null)
        {
            onLanguageChanged(language);
        }
    }
Exemple #3
0
    bool checkEntryIntegrity(SerializedNestedStrings languageData, string key, string value, SerializedNestedStrings englishData)
    {
        if (englishData != null && englishData != languageData)
        {
            // Check parameter counts
            var paramCount = 0;
            while (true)
            {
                if (!value.Contains("{" + paramCount.ToString() + "}"))
                {
                    break;
                }
                paramCount++;
            }
            var englishText = englishData[key];
            if (englishText != null)
            {
                var englishParamCount = 0;
                while (true)
                {
                    if (!englishText.Contains("{" + englishParamCount.ToString() + "}"))
                    {
                        break;
                    }
                    englishParamCount++;
                }
                if (paramCount != englishParamCount)
                {
                    Debug.LogWarning($"Language {getLanguageIdName(languageData)} has an inconsistent parameter count in key {key}");
                }
            }
        }

        return(true);
    }
    public static SerializedNestedStrings deserialize(string serializedData, SerializedNestedStrings existingStrings = null)
    {
        serializedData = serializedData.Replace(((char)13).ToString(), ""); //Remove any instances of carriage return
        if (existingStrings == null)
        {
            existingStrings = new SerializedNestedStrings();
        }

        deserializeData(existingStrings.rootData, serializedData.Split('\n'), 0, 0);
        return(existingStrings);
    }
    public static SerializedNestedStrings deserialize(string serializedData)
    {
        serializedData = serializedData.Replace(((char)13).ToString(), "");             //Remove any instances of carriage return

        List <string>           lines   = new List <string>(serializedData.Split('\n'));
        SerializedNestedStrings newData = new SerializedNestedStrings();

        string currentKeyBase = "";

        for (int i = 0; i < lines.Count; i++)
        {
            string line     = lines[i];
            int    tabCount = Regex.Match(line, @"^\t*").Value.Length,
                   dotCount = currentKeyBase.Split('.').Length - 1;
            while (tabCount < dotCount)
            {
                //Key is up from previous line in hierarchy
                //Remove "{key}." from current hierarchy string to go up one level
                if (dotCount == 1)
                {
                    currentKeyBase = "";
                }
                else
                {
                    currentKeyBase = Regex.Replace(currentKeyBase, @"(.*)\.[^\.]*.$", @"$1.");
                }
                dotCount--;
            }
            if (line.Contains("="))
            {
                //line is string value, add to deserialized data
                string key   = Regex.Replace(line.Split('=')[0], @"^\t*", ""),
                       value = Regex.Replace(line, @"^[^=]*=(.*)", @"$1");
                newData[currentKeyBase + key] = value;
            }
            else
            {
                //line is beginning of a group, increase nest level by adding line to keystring base
                currentKeyBase += Regex.Replace(line, @"^\t*", "") + ".";
            }
        }

        return(newData);
    }
Exemple #6
0
    public void loadLocalizedText(string filename)
    {
        string filePath = Path.Combine(Application.streamingAssetsPath, filename);

        if (!File.Exists(filePath))
        {
            filePath = filePath.Replace(language, "English");
            Debug.Log("Language " + language + " not found. Using English");
            language = "English";
        }
        if (File.Exists(filePath))
        {
            System.DateTime started = System.DateTime.Now;
            localizedText = SerializedNestedStrings.deserialize(File.ReadAllText(filePath));
            System.TimeSpan timeElapsed = System.DateTime.Now - started;
            Debug.Log("Language " + language + " loaded successfully. Deserialization time: " + timeElapsed.TotalMilliseconds + "ms");
        }
        else
        {
            Debug.LogError("No English json found!");
        }
    }
 //Use the second row sheet buffer to get proper codenames for langauges
 string getLanguageIdName(SerializedNestedStrings languageData)
 {
     return(languageData[idNameKey]);
 }
Exemple #8
0
    public void updateLanguages()
    {
        var languages = new Dictionary <string, SerializedNestedStrings>();
        SerializedNestedStrings englishData = null;

        var sheetTitles = new List <string>();

        var missingValues = new Dictionary <string, Dictionary <string, int> >();

        for (int i = 1; i <= subsheetCount; i++)
        {
            var sheet      = GDocService.GetSpreadsheet(spreadsheetId, i);
            var sheetTitle = sheet.Title.Text;
            sheetTitles.Add(sheetTitle);

            // Ran only at start of loop, but necessary here so we don't have to read the first sheet twice
            if (i == 1)
            {
                languages   = generateLanguageDict(sheet);
                englishData = languages.FirstOrDefault().Value;
                foreach (var language in languages)
                {
                    missingValues[language.Key] = new Dictionary <string, int>();
                }
            }

            // Missing values structure is initially populated with every language and sheet title set to 0 missing values
            foreach (var language in languages)
            {
                missingValues[language.Key][sheetTitle] = 0;
            }

            foreach (ListEntry row in sheet.Entries)
            {
                string rowKey = "";
                foreach (ListEntry.Custom element in row.Elements)
                {
                    if (element.LocalName.Equals(KeyIdentifier))
                    {
                        rowKey = element.Value;
                    }
                    else if (languages.ContainsKey(element.LocalName))
                    {
                        var languageData = languages[element.LocalName];

                        if (!string.IsNullOrEmpty(element.Value))
                        {
                            var cleansedEntry = cleanseEntry(element.Value);

                            if (checkEntryIntegrity(languageData, rowKey, cleansedEntry, englishData))
                            {
                                languageData[rowKey] = cleansedEntry;
                            }
                        }
                        else
                        {
                            if (!string.IsNullOrEmpty(englishData[rowKey]))
                            {
                                missingValues[element.LocalName][sheetTitle]++;
                            }
                        }
                    }
                }
            }
        }

        string fullLanguagesPath = Path.Combine(Application.dataPath, languagesPath);

        foreach (var languageData in languages)
        {
            string name = getLanguageIdName(languageData.Value);
            File.WriteAllText(Path.Combine(fullLanguagesPath, name), languageData.Value.ToString());

            var languageId = languageData.Value["generic.idname"];
            if (string.IsNullOrEmpty(languageId) || !languagesData.languages.Any(a => a.getLanguageID().Equals(languageId)))
            {
                Debug.LogWarning($"Language {languageData.Key} not found in languages data.");
            }
            else
            {
                var metaRecordedStatus = languageData.Value["meta.recorded"];
                if (string.IsNullOrEmpty(metaRecordedStatus) || !metaRecordedStatus.Equals("Y", System.StringComparison.OrdinalIgnoreCase))
                {
                    Debug.LogWarning($"Language {languageData.Key} does not have metadata recorded in google sheets");
                }
            }
        }

        // Format missing text report
        var missingValuesLanguageReports = missingValues
                                                                                                                                      //.Where(language => language.Value.Any(sheet => sheet.Value > 0))    // Select from languages who have missing values whatsoever
                                           .Select(language => language.Key + ": " + language.Value.Sum(sheet => sheet.Value) + " - " // Sum up all missing values in a language
                                                   + string.Join(", ", language.Value                                                 // Then list out each subsheet in that language and its amount of missing values
                                                                 .Where(sheet => sheet.Value > 0)                                     // Exclude any sheets with no missing values
                                                                 .Select(sheet => sheet.Key + ": " + sheet.Value.ToString())));

        // Write to log
        var reportText = "Push this file with any localization updates.\n\n";

        reportText += $"Last pulled:\n{System.DateTime.Now.ToString()}\n";
        reportText += "\nThis is the order the sheets were found in. If github tries to change them, rearrange the cells so they match this and update language content again.\n"
                      + string.Join("\n", sheetTitles) + "\n";
        reportText += "\nHow many values are missing translations from each language (doesn't count non-game pages such as Steam Store):\n"
                      + string.Join("\n", missingValuesLanguageReports) + "\n";
        File.WriteAllText(Path.Combine(Application.dataPath, reportFile), reportText);

        Debug.Log("Language content updated");
    }
Exemple #9
0
    public List <LanguageFontCharData> GetMissingFontCharData(TMPFont forceFont = null, Language forceLanguage = null)
    {
        string fullLanguagesPath = Path.Combine(Application.dataPath, languagesPath);
        string fullCharsPath     = Path.Combine(Application.dataPath, charsPath);
        var    missingCharData   = new List <LanguageFontCharData>();

        foreach (var language in LanguagesData.instance.languages)
        {
            if (forceLanguage != null && forceLanguage != language)
            {
                continue;
            }

            var filePath = Path.Combine(fullLanguagesPath, language.getFileName());
            var fontDict = SerializedNestedStrings.deserialize(File.ReadAllText(filePath)).getSubData("meta.font").subData;
            foreach (var fontKVPair in fontDict)
            {
                if (LocalizationManager.parseFontCompabilityString(language, fontKVPair.Value.value))
                {
                    // Font is marked as compatible
                    var font = TMPFontsData.instance.fonts.FirstOrDefault(a => a.idName.Equals(fontKVPair.Key));

                    if (forceFont != null && forceFont != font)
                    {
                        continue;
                    }

                    if (font == null)
                    {
                        Debug.LogWarning(fontKVPair.Key + " is missing from TMP Fonts Data asset");
                        continue;
                    }
                    if (font.fontAsset == null)
                    {
                        Debug.LogWarning(fontKVPair.Key + " is missing associated TMPro font in TMP Fonts asset");
                        continue;
                    }

                    var charString = File.ReadAllText(Path.Combine(fullCharsPath, language.getFileName() + "Chars.txt"));
                    charString = string.Join("", charString.Distinct());
                    List <char> currentChars = charString.ToCharArray().ToList();
                    currentChars.Add('a');

                    // Check fonts AND fallbacks
                    var fallbackList = new List <TMP_FontAsset>();
                    fallbackList.Add(font.fontAsset);                           // Current language
                    fallbackList.AddRange(font.fontAsset.fallbackFontAssets);   // language's fallbacks
                    fallbackList.AddRange(TMP_Settings.fallbackFontAssets);     // Global fallbacks
                    fallbackList = fallbackList.Distinct().ToList();

                    foreach (var fontAsset in fallbackList)
                    {
                        var missingChars = new List <char>();
                        // NO idea why but the hasCharacters() function seems to just be true all the time, so also check for null/any

                        missingChars = currentChars.Where(a => !fontAsset.characterDictionary.ContainsKey((int)a)).ToList();

                        if (missingChars != null && missingChars.Any())
                        {
                            currentChars = missingChars;
                        }
                        else
                        {
                            currentChars = null;
                            break;
                        }
                    }
                    if (currentChars != null)
                    {
                        currentChars = currentChars.Except(ignoreChars.ToCharArray()).ToList();
                        if (currentChars.Any())
                        {
                            missingCharData.Add(new LanguageFontCharData(language, font, string.Join("", currentChars)));
                        }
                    }
                }
            }
        }
        return(missingCharData
               .OrderBy(a => a.font.fontAsset.name)
               .ThenBy(a => a.language.getLanguageID())
               .ToList());
    }