Esempio n. 1
0
        public void YarnImporterUtility_CanCreateLocalizationInLocalizationDatabase()
        {
            // Arrange: Import a yarn script and create a localization
            // database for it
            string fileName = Path.GetRandomFileName();
            string path     = Path.Combine("Assets", fileName + ".yarn");

            createdFilePaths.Add(path);
            File.WriteAllText(path, TestYarnScriptSource);
            AssetDatabase.Refresh();
            var importer = AssetImporter.GetAtPath(path) as YarnImporter;
            var importerSerializedObject = new SerializedObject(importer);

            YarnImporterUtility.CreateNewLocalizationDatabase(importerSerializedObject);
            createdFilePaths.Add(AssetDatabase.GetAssetPath(importer.localizationDatabase));

            var databaseSerializedObject = new SerializedObject(importer.localizationDatabase);

            // Act: Create a new localization CSV file for some new language
            LocalizationDatabaseUtility.CreateLocalizationWithLanguage(databaseSerializedObject, AlternateLocaleCode);
            YarnImporterUtility.CreateLocalizationForLanguageInProgram(importerSerializedObject, AlternateLocaleCode);

            foreach (var loc in importer.localizationDatabase.Localizations)
            {
                createdFilePaths.Add(AssetDatabase.GetAssetPath(loc));
            }

            foreach (var loc in importer.localizations)
            {
                createdFilePaths.Add(AssetDatabase.GetAssetPath(loc.text));
            }

            importer.SaveAndReimport();

            // Assert: Verify that it exists, contains the string table
            // entries we expect, and has the language we expect.
            var expectedLanguages = new HashSet <string> {
                importer.baseLanguageID, AlternateLocaleCode
            }.OrderBy(n => n);
            var foundLanguages = importer.programContainer.localizations.Select(l => l.languageName).OrderBy(n => n);

            CollectionAssert.AreEquivalent(expectedLanguages, foundLanguages, $"The locales should be what we expect to see");
        }
Esempio n. 2
0
        public void YarnImporterUtility_CanUpdateLocalizedCSVs_WhenBaseScriptChanges()
        {
            // Arrange: Import a yarn script and create a localization
            // database for it, create an alternate localization for it
            string fileName = Path.GetRandomFileName();
            string path     = Path.Combine("Assets", fileName + ".yarn");

            createdFilePaths.Add(path);
            File.WriteAllText(path, TestYarnScriptSource);
            AssetDatabase.Refresh();
            var importer = AssetImporter.GetAtPath(path) as YarnImporter;
            var importerSerializedObject = new SerializedObject(importer);

            YarnImporterUtility.CreateNewLocalizationDatabase(importerSerializedObject);
            var localizationDatabaseSerializedObject = new SerializedObject(importer.localizationDatabase);

            LocalizationDatabaseUtility.CreateLocalizationWithLanguage(localizationDatabaseSerializedObject, AlternateLocaleCode);

            YarnImporterUtility.CreateLocalizationForLanguageInProgram(importerSerializedObject, AlternateLocaleCode);

            var unmodifiedBaseStringsTable      = StringTableEntry.ParseFromCSV((importerSerializedObject.targetObject as YarnImporter).baseLanguage.text);
            var unmodifiedLocalizedStringsTable = StringTableEntry.ParseFromCSV((importerSerializedObject.targetObject as YarnImporter).localizations.First(l => l.languageName == AlternateLocaleCode).text.text);

            // Act: modify the imported script so that lines are added,
            // changed and deleted, and then update the localized CSV
            // programmatically

            File.WriteAllText(path, TestYarnScriptSourceModified);
            AssetDatabase.Refresh();
            YarnImporterUtility.UpdateLocalizationCSVs(importerSerializedObject);

            var modifiedBaseStringsTable      = StringTableEntry.ParseFromCSV((importerSerializedObject.targetObject as YarnImporter).baseLanguage.text);
            var modifiedLocalizedStringsTable = StringTableEntry.ParseFromCSV((importerSerializedObject.targetObject as YarnImporter).localizations.First(l => l.languageName == AlternateLocaleCode).text.text);

            // Assert: verify the base language string table contains the
            // string table entries we expect, verify the localized string
            // table contains the string table entries we expect

            System.Func <StringTableEntry, string> CompareIDs   = t => t.ID;
            System.Func <StringTableEntry, string> CompareLocks = t => t.Lock;

            var tests = new[] {
Esempio n. 3
0
        public void YarnImporterUtility_CanCreateNewLocalizationDatabase()
        {
            // Arrange: Import a yarn script
            string fileName = Path.GetRandomFileName();

            string path = Path.Combine("Assets", fileName + ".yarn");

            createdFilePaths.Add(path);

            File.WriteAllText(path, TestYarnScriptSource);
            AssetDatabase.ImportAsset(path);
            AssetDatabase.Refresh();
            var importer         = AssetImporter.GetAtPath(path) as YarnImporter;
            var serializedObject = new SerializedObject(importer);

            var localizationDatabaseAfterImport = importer.localizationDatabase;

            // Act: create a new localization database.
            YarnImporterUtility.CreateNewLocalizationDatabase(serializedObject);

            importer.SaveAndReimport();

            // Assert: Verify that the new localization database exists,
            // and contains a single localization, and that localization
            // contains the string table entries we expect.
            Assert.Null(localizationDatabaseAfterImport, "The script should not have a localization database after initial creation");

            Assert.NotNull(importer.localizationDatabase, "Importer should have a localization database");
            createdFilePaths.Add(AssetDatabase.GetAssetPath(importer.localizationDatabase));

            var db = importer.localizationDatabase;

            Assert.AreEqual(1, db.Localizations.Count(), "Localization database should have a single localization");
            createdFilePaths.Add(AssetDatabase.GetAssetPath(importer.localizationDatabase.Localizations.First()));

            var localization = db.Localizations.First();

            Assert.AreEqual(localization.LocaleCode, importer.baseLanguageID, "Localization locale should match script's language");

            Assert.Contains(importer.baseLanguageID, ProjectSettings.TextProjectLanguages, "Script language should be present in the project language settings");
        }
Esempio n. 4
0
    private void DrawLocalizationGUI()
    {
        using (var changed = new EditorGUI.ChangeCheckScope())
        {
            var previousLocalizationDatabase = localizationDatabaseProperty.objectReferenceValue as LocalizationDatabase;

            // Show the 'localization database' property
            EditorGUILayout.PropertyField(localizationDatabaseProperty);

            // If this changed to a valid value, update that database so
            // that it tracks all selected programs
            if (changed.changed)
            {
                var newObjectReference = localizationDatabaseProperty.objectReferenceValue;

                if (previousLocalizationDatabase != null && previousLocalizationDatabase != newObjectReference)
                {
                    // The property used to refer to a localization
                    // database, but that's changed. Tell the previous
                    // value to stop tracking this program.
                    foreach (YarnImporter importer in serializedObject.targetObjects)
                    {
                        if (importer.programContainer == null)
                        {
                            continue;
                        }
                        previousLocalizationDatabase.RemoveTrackedProgram(importer.programContainer);

                        // Mark that the localization database has changed,
                        // so needs to be saved
                        EditorUtility.SetDirty(previousLocalizationDatabase);
                    }
                }

                // Tell the new database that it should track us
                if (newObjectReference is LocalizationDatabase database)
                {
                    foreach (YarnImporter importer in serializedObject.targetObjects)
                    {
                        // If we don't actually have a program (because of
                        // a compile error), there's nothing to do here
                        if (importer.programContainer == null)
                        {
                            continue;
                        }
                        database.AddTrackedProgram(importer.programContainer);

                        // Mark that the localization database should save
                        // changes
                        EditorUtility.SetDirty(previousLocalizationDatabase);
                    }
                }
            }
        }

        // If no localization database is provided, offer a button that
        // will create a new one that 1. tracks this script 2. has a
        // localization set to this script's base language 3. and also we
        // make sure that this project's language list includes this
        // program's base language.
        if (localizationDatabaseProperty.objectReferenceValue == null)
        {
            if (GUILayout.Button("Create New Localization Database"))
            {
                YarnImporterUtility.CreateNewLocalizationDatabase(serializedObject);
            }
        }

        // For every localization in the localization database:
        // - If we have a TextAsset for it, show it here
        // - If we don't, create a button that creates one
        //
        // We only do this if we're editing a single object, because each
        // separate script will have its own translations.
        if (serializedObject.isEditingMultipleObjects == false && localizationDatabaseProperty.objectReferenceValue != null)
        {
            EditorGUI.indentLevel += 1;
            var importer             = serializedObject.targetObject as YarnImporter;
            var localizationDatabase = localizationDatabaseProperty.objectReferenceValue as LocalizationDatabase;

            var languagesList = new List <string>();
            languagesList.Add(importer.baseLanguageID);

            // Expose the base language asset in the inspector, but disable
            // it because it's always a derived sub-asset
            using (new EditorGUI.DisabledScope(true))
                using (new EditorGUILayout.HorizontalScope())
                {
                    EditorGUILayout.PropertyField(baseLanguageProperty, new GUIContent(importer.baseLanguageID));

                    // Not actually used, but makes this base language item
                    // visually consistent with the additional ones below
                    GUILayout.Button("-", EditorStyles.miniButton, GUILayout.ExpandWidth(false));
                }


            foreach (SerializedProperty localization in localizationsProperty)
            {
                var nameProperty           = localization.FindPropertyRelative("languageName");
                var assetReferenceProperty = localization.FindPropertyRelative("text");
                var languageName           = nameProperty.stringValue;
                var languageDisplayName    = Cultures.GetCulture(languageName).DisplayName;

                using (new EditorGUILayout.HorizontalScope())
                {
                    EditorGUILayout.PropertyField(assetReferenceProperty, new GUIContent(languageDisplayName));

                    if (GUILayout.Button("-", EditorStyles.miniButton, GUILayout.ExpandWidth(false)))
                    {
                        // We delete this property twice:
                        // - once to clear the value from the array entry
                        // - again to remove the cleared entry from the
                        //   array
                        //
                        // (If the entry is already empty, the first delete
                        // will remove it; the second delete appears to be
                        // a no-op, so it's safe.)
                        localization.DeleteCommand();
                        localization.DeleteCommand();
                    }
                }


                // Mark that we've seen this language name
                languagesList.Add(languageName);
            }

            // For each language that's present in the localization
            // database but not present in this script, offer buttons that
            // create a CSV for that language
            var languagesMissing = localizationDatabase.GetLocalizationLanguages().Except(languagesList);

            foreach (var language in languagesMissing)
            {
                if (GUILayout.Button($"Create {language} Localization"))
                {
                    YarnImporterUtility.CreateLocalizationForLanguageInProgram(serializedObject, language);
                }
            }

            // Show a warning for any languages that the script has a
            // localization for, but that the database doesn't call for
            var languagesExtraneous = languagesList.Except(localizationDatabase.GetLocalizationLanguages());

            if (languagesExtraneous.Count() > 0)
            {
                EditorGUILayout.HelpBox($"This script has localizations for the following languages, but the localization database isn't set up to use them: {string.Join(", ", languagesExtraneous)}", MessageType.Warning);
            }

            // TODO: is it possible to interleave the property fields for
            // existing localisations with buttons, in alphabetical order
            // of language code?

            EditorGUI.indentLevel -= 1;

            if (GUILayout.Button("Update Localizations"))
            {
                YarnImporterUtility.UpdateLocalizationCSVs(serializedObject);
            }

            EditorGUILayout.HelpBox("To add a new localization, select the Localization Database, and click Create New Localization.", MessageType.Info);
        }
    }