Custom Solution - Read All Subtitle / Dialogue Text From Json at Runtime for Localization

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
qwertywasd17
Posts: 3
Joined: Mon Jan 01, 2024 8:56 pm

Custom Solution - Read All Subtitle / Dialogue Text From Json at Runtime for Localization

Post by qwertywasd17 »

I'm working with an SDK and platform that requires a language json file and specific format. (Tony, you probably know the one)

The format goes:

Code: Select all

{
  "_meta": {
    "maxChars": {
       "welcome": 50
     }
   },
   "en": {
     "welcome": "Welcome"
   }, 
   "es": {
     "welcome": "Bienvenido"
   }
 }
I'll have to swap languages when their SDK function is called. I can do that using

Code: Select all

DialogueManager.SetLanguage(languageKey);
, but I'm stuck trying to call the json at runtime. I've set up 'es' as a template field type Localization, but I won't be implementing the localized text this way. The platform will be translating and uploading the text. They need my solution to read the json using their language code to point at the right localized text.

My key question is how do I set all conversation lines to the localized text language the user selects before the gameplay starts? The option to swap is already given before any dialogue begins.

Here's an example of the keys and values I use in the json file:

Code: Select all

    "intro7": "Press the Down Arrow Key to activate Teds cold power.",
    "intro8": "Great job! You’ve frozen the little guy! It’s now a solid state slime.",
    "intro9": "Look at the Micro Cam.",
I'm incrementing a string on each line of dialogue using a sequencer command because it has to sync up with the SDK's Text-to-Speech.

To vet my own question... here's my steps (thinking out loud here)
- Load DialogueDatabase
- MainMenu loads
- The user selects a language
- TDS DialougeManager.SetLanguage(languageKey) updates the key (ex: from "en" to "es")
- The DialolgueDatabase or separate solution using Subtitle Text reads the keys and values from language.json
- All dialogue in conversations now displays the localized text read from the .json file provided by the platform's team
- For testing (as per the requirements) if the key's value is "" (blank) it will display no text in the subtitle text

Thanks in advance for your help. Let me know if I should share any more info. Not sure how much I can actually share without having to read the contract though.
User avatar
Tony Li
Posts: 22110
Joined: Thu Jul 18, 2013 1:27 pm

Re: Custom Solution - Read All Subtitle / Dialogue Text From Json at Runtime for Localization

Post by Tony Li »

Hi,

Do you want to do this at design time so your dialogue database is ready to go in the build, or do you want to get the languages.json fresh at runtime?

If at runtime, do you want to get all of the lines of dialogue when the game starts, or make a request for each line of dialogue at the moment it's going to be displayed?

If it's at runtime, here are some thoughts:

- Tick the Dialogue Manager's Other Settings > Instantiate Database checkbox. This way you can change the database at runtime without affecting the original asset.

- To get all of the lines of dialogue when the game starts, create your big languages.json file. For example:

Code: Select all

var sb = new StringBuilder();
sb.Append("{\n");

// Meta:
sb.Append("  \"_meta\": {\n    \"maxChars\": {\n");
foreach (var conversation in DialogueManager.masterDatabase.conversations)
{
    foreach (var entry in conversation.dialogueEntries)
    {
        if (string.IsNullOrEmpty(entry.DialogueText)) continue;
        sb.Append($"      \"{entry.DialogueText}\": 50,\n");
    }
}
sb.Append("    }\n  },\n");

// Lines by language:
var languages = new string[] { "en", "es" };
foreach (var language in languages)
{
    Localization.language = language;
    sb.Append($"  \"{language}\": {{\n");
    foreach (var conversation in DialogueManager.masterDatabase.conversations)
    {
        foreach (var entry in conversation.dialogueEntries)
        {
            if (string.IsNullOrEmpty(entry.DialogueText)) continue;
            sb.Append($"    \"{entry.DialogueText}\": \"{entry.currentDialogueText}\",\n");
        }
    }
    sb.Append("    }\n  },\n");
}
sb.Append("}");
string json = sb.ToString();
I may be completely off the mark in my assumption of what you want to do, so let me know if I can provide other details.
qwertywasd17
Posts: 3
Joined: Mon Jan 01, 2024 8:56 pm

Re: Custom Solution - Read All Subtitle / Dialogue Text From Json at Runtime for Localization

Post by qwertywasd17 »

Ok that's potentially useful. I haven't worked with json before this, so it's a learning experience. I understand the basics, but I haven't thought about how to build my own json string.

Once I have the string, how can I get the DialogueDatabase to read it for each respective language code?

I think it would be better to preload all translated conversations before game play (during main menu).
User avatar
Tony Li
Posts: 22110
Joined: Thu Jul 18, 2013 1:27 pm

Re: Custom Solution - Read All Subtitle / Dialogue Text From Json at Runtime for Localization

Post by Tony Li »

If you know you can get the translations before building and shipping the game to players, I recommend writing an editor script to do this. You can put those translations right back into the dialogue database. Make sure to call EditorUtility.SetDirty(yourDatabase) to tell Unity to save the changes to disk.

Alternatively, it's fine to read and process the json on startup. Does the SDK return a json file in the same format? Like, if the file you send is:

Code: Select all

{
  "_meta": {
    "maxChars": {
       "intro9": 50
     }
   },
   "en": {
     "intro9": "Look at the Micro Cam."
   }, 
   "es": {
     "intro9": "",
   }
}
Does it send back the same json file but with the translation for "es"?

Code: Select all

{
  "_meta": {
    "maxChars": {
       "intro9": 50
     }
   },
   "en": {
     "intro9": "Look at the Micro Cam."
   }, 
   "es": {
     "intro9": "Mira la Micro Cam.",
   }
}
If so, I recommend looking into Json.NET (https://www.newtonsoft.com/json). Unity's JsonUtility can't handle the json format above. It expects everything to be structured the same. But in the json above, the structure of the "_meta" record is different from the structures of "en" and "es.
qwertywasd17
Posts: 3
Joined: Mon Jan 01, 2024 8:56 pm

Re: Custom Solution - Read All Subtitle / Dialogue Text From Json at Runtime for Localization

Post by qwertywasd17 »

I leveraged your for-loop structure to update each line of dialogue with the corresponding line in the language.json file. This solution builds a string using the conversation's title and ID number. I had to modify the dialogue nodes to make it work this way, but I only did it like that because I was trying not to break anything else. Next time, I'll set this up better ahead of time.

Code: Select all

        public void UpdateDatabaseWithLanguage()
        {
            // Loop through all conversations in the database
            foreach (var conversation in DialogueManager.masterDatabase.conversations)
            {
                // Loop through each dialogue entry in the conversation
                foreach (var entry in conversation.dialogueEntries)
                {
                    foreach (var field in entry.fields)
                    {
                        if (field.title == "Title")
                        {
                            string textKey = conversation.Title + entry.id;
                            string localizedText = GetText(textKey); // Get json text from _langNode[key]

                            entry.DialogueText = localizedText;
                        }
                    }
                }
            }
        }
Thanks Tony
User avatar
Tony Li
Posts: 22110
Joined: Thu Jul 18, 2013 1:27 pm

Re: Custom Solution - Read All Subtitle / Dialogue Text From Json at Runtime for Localization

Post by Tony Li »

Hi Allen,

That's totally fine! It's what I would have done myself.
Post Reply