Localize arguments when formating

Hello.
I don’t know how to google this correctly :slight_smile:

Consider the next example:
String Tables →

  • Dialogs →
    – say_hello = “Hello {Name}!”
  • Names →
    – name_tim - “Tim”
    – name_bart - “Bart”

The name to display will be chosen at runtime.
For now, to display the correct name I need to wait for name to complete the GetLocalizedString async operation. It may need an entire frame because synchronous localization is not done yet.
Then I need to wait for dialog to localize with the provided argument, which also may require the entire frame.
Such behavior will produce noticeable text popping on the screen while localization is loading.

What is the right way to localize arguments?
Is there a way to localize like this: “Hello {Names.name_tim}!”?

Ps
Example is synthetic, actual use is a bit more complex.

I’ve read all manual and didn’t find anything related

You can mark your tables as preload https://docs.unity3d.com/Packages/com.unity.localization@0.11/manual/StringTables.html#preloading
Look at the Samples we have, one shows how to wait for preloading to complete. Once preloading is done then strings will be returned during the same frame.
Do you plan to localize the names? We do plan to support embedding localized values like this in the future, the synchronous support is the first step towards this.
For now it sounds like preloading should solve your problems.

Yes, kinda

That’s good.

It would be cool to have a setting to enable this on every table. But synchronous loading solves this problem better.

Thanks!

1 Like

@karl_jones It’s the question for another thread but maybe it’s quite simple to solve, so…

I want my editor code to add entries to tables.
The problem is that I need to call these 2 methods:

LocalizationEditorSettings.EditorEvents.RaiseTableEntryAdded(table, entry);
LocalizationEditorSettings.EditorEvents.RaiseCollectionModified(null, table);

But I can’t, because they are internal methods.

I made a workaround in the past. I grabbed source code of the package and created the embedded package (placed source code inside Packages folder).
This way I was able to create required code and call these internal methods.
Now the problem with this solution is: I can’t easily upgrade to a newer version of the localization package:(

Is there a better way to properly add entries to tables?

Hi,
Not at the moment but it’s something we should support. I’m not sure exposing the events is the answer though, we should just update when you call the add method. Could you file a bug report?

Do I need to attach a repro project?

Actually it’s ok. I already have an idea for a fix so I’ll raise the bug myself.

Thanks! I’ve almost filled up the report, but with my poor English it’s hard to understand:)
Glad I saw your message.

Is there any timestamp when this could be fixed?
Should I just again use the embedded package(with the new package version) or is it worth waiting?

I think we will probably move some of those events directly into the tables and make them static so they can be called directly by the tables so you won’t need to call them. So I would not use the events anymore and wait for the fix unless it’s a problem in which case carry on calling the event for the moment. Hopefully we should have a new release in a few weeks and ill try and get this in with it

1 Like

Hi. Can you tell me if that’s a possibility right now?

Is this what you want? https://docs.unity3d.com/Packages/com.unity.localization@1.4/manual/Smart/Persistent-Variables-Source.html#nested-translations

Not really. When I rename a entry from the code, the table goes to None (String). I call SetDirty, but it doesn’t give any result. I thought there must be a way to update the table

Can you share the code you are using?

public class NameLocalizationUpdater : UnityEditor.AssetModificationProcessor
    {
        private static AssetMoveResult OnWillMoveAsset(string sourcePath, string destinationPath)
        {
            var finalResult = AssetModificationHook.OnWillMoveAsset(sourcePath, destinationPath);

            var directoryName = Path.GetDirectoryName(sourcePath);
            ElementLocalization nodeLocalization = null;

            switch (directoryName)
            {
                case "Assets/GameAssets/Abilities":
                {
                    var localizedAsset = (AbilityAsset)AssetDatabase.LoadAssetAtPath(sourcePath, typeof(AbilityAsset));
                        nodeLocalization = localizedAsset.Localization;
                    break;
                }
            }

            if (nodeLocalization != null)
            {
                Rename(nodeLocalization.TitleValue, destinationPath);
                Rename(nodeLocalization.DescriptionValue, destinationPath);
            }
           
            return finalResult;
        }

        private static void Rename(LocalizedString localizedString, string destinationPath)
        {
            var tableCollectionName = localizedString.TableReference.TableCollectionName;
            var localizationEditorSettings = LocalizationEditorSettings.GetStringTableCollection(tableCollectionName);
            var sharedData = localizationEditorSettings.SharedData;
           
            var entry = sharedData.GetEntryFromReference(localizedString.TableEntryReference);
            var key = sharedData.GetKey(entry.Id);
           
            var file = Path.GetFileNameWithoutExtension(destinationPath);
            var extension = Path.GetExtension(key);
           
            Undo.RecordObject(sharedData, "Rename key entry");
            sharedData.RenameKey(entry.Id, file + extension);
            EditorUtility.SetDirty(sharedData);
           
            Debug.Log($"[Rename] Localization was renamed from -> {key} to -> {file + extension}");
        }
    }

Oh you are trying to rename the tables?
That should be done through the API

var s = LocalizationEditorSettings.GetStringTableCollection("name");
s.SetTableCollectionName("new name");

The names of the files are important to addressables so only use the API to rename it otherwise it may break things.
https://docs.unity3d.com/Packages/com.unity.localization@1.5/manual/Addressables.html

Thank you, but no. I’m trying to rename the Table Entry name. After renaming, they keep looking for the old name

Here’s the solution

EditorUtility.SetDirty(asset);

localizedString.TableEntryReference = sharedData.GetKey(entry.Id);

You want to change the reference? It would be better to use the id than the key, it’s safer.

localizedString.TableEntryReference = entry.Id;