Skip to content

Localisation

Dione Mentis requested to merge localisation into dev

@grgml this is a draft of the docs so you have context for merging

Understanding the Translation File Structure

Our translation file uses a nested JSON structure where each UI element has a type and value at minimum. Some elements have additional attributes or nested structures depending on their complexity and purpose.

File Organization and Structure

Pages and Layout Hierarchy

The translation file is organized to mirror the application's structure, making it easier to find and maintain translations. The top level of the file contains a "pages" object, with each major section of the application represented as a nested object.

{
  "pages": {
    "admin": { ... },
    "aiBookDesigner": { ... },
    "common": { ... },
    "dash": { ... },
    "knowledgeBase": { ... },
    "login": { ... },
    "newBook": { ... },
    "passwordReset": { ... },
    "previewAndPublish": { ... },
    "producer": { ... },
    "signup": { ... }
  }
}

The Common Section

The "common" section serves a special purpose in our translation system. It contains translations that are used across multiple pages of the application. This approach:

  • Reduces duplication
  • Ensures consistency
  • Simplifies maintenance
  • Centralizes shared UI elements

For example, form elements like email and password inputs appear on multiple pages (login, signup, password reset). Instead of duplicating these translations, they are stored once in the common section:

{
  "pages": {
    "common": {
      "form": {
        "email": {
          "type": "input(label)",
          "value": "Email",
          "placeholder": {
            "type": "input(placeholder)",
            "value": "Enter your email address"
          },
          "errors": {
            "noValue": {
              "type": "error",
              "value": "Email is required"
            }
          }
        },
        "password": {
          "type": "input(label)",
          "value": "Password",
          "placeholder": {
            "type": "input(placeholder)",
            "value": "Enter your password"
          },
          "errors": {
            "noValue": {
              "type": "error",
              "value": "Password is required"
            }
          }
        }
      }
    }
  }
}

Form Elements

Input Fields

Here's how to handle an input field's translation structure:

{
  "email": {
    "type": "input(label)",
    "value": "Email address"
  },
  "placeholder": {
    "type": "input(placeholder)",
    "value": "Enter your email address"
  },
  "explanation": {
    "type": "input(detail)",
    "value": "We'll use this email for account recovery"
  },
  "errors": {
    "noValue": {
      "type": "error",
      "value": "Email is required"
    },
    "invalidEmail": {
      "type": "error",
      "value": "This is not a valid email address"
    }
  }
}

Selection Controls

Selection controls (dropdowns, radio buttons, checkboxes) are used when users need to choose from predefined options. They have a more complex structure that includes the label, options, and often additional explanatory text.

{
  "format": {
    "type": "select(label)",
    "value": "Format:"
  },
  "options": {
    "pdf": {
      "value": "PDF"
    },
    "epub": {
      "value": "EPUB"
    },
    "web": {
      "value": "Web"
    }
  },
  "explanation": {
    "type": "select(detail)",
    "value": "Choose the format for your book export"
  }
}

For complex options that need additional explanation:

{
  "license": {
    "type": "select(label)",
    "value": "Copyright license"
  },
  "options": {
    "allRightsReserved": {
      "value": "All Rights Reserved",
      "detail": {
        "type": "option(detail)",
        "value": "Your work cannot be distributed without your express consent"
      }
    },
    "creativeCommons": {
      "value": "Creative Commons",
      "detail": {
        "type": "option(detail)",
        "value": "Some rights are reserved based on the specific license you select"
      }
    }
  }
}

Toggle Switches

Switches are used for binary settings (on/off, enable/disable). They often need both a label and an explanation of their effects:

        "aiDesigner": {
          "type": "switch(label)",
          "value": "AI Book Designer (Beta)",
          "detail": {
            "type": "switch(detail)",
            "value": "Users with edit access to this book can use AI writing prompts."
          }
        }

Navigation Elements

Menus

Menus organise navigation and actions. They can include different types of items:

  • Use link(text) for navigation to other pages
  • Use action for operations like logout or delete
{
  "menu": {
    "type": "menu",
    "options": {
      "admin": {
        "type": "link(text)",
        "value": "Admin"
      },
      "logout": {
        "type": "action",
        "value": "Log out"
      },
      "dashboard": {
        "type": "link(text)",
        "value": "Dashboard"
      }
    }
  }
}

System Messages and Notifications

Simple Messages

Use the message type for simple status updates or state information:

{
  "status": {
    "type": "message",
    "value": "Last synced %{timestamp}"
  }
}

Notifications

Use the notifications structure for more complex messages that appear on pop ups and might need titles or different severity levels:

{
  "notifications": {
    "error": {
      "title": {
        "type": "title",
        "value": "Error"
      },
      "messages": {
        "general": {
          "type": "error",
          "value": "Something went wrong. You will be redirected back to your dashboard."
        }
      }
    }
  }
}

Page Structure Elements

Titles and Headings

{
  "title": {
    "type": "title",
    "value": "Create New Book"
  },
  "sections": {
    "upload": {
      "heading": {
        "type": "heading",
        "value": "Upload your files"
      },
      "description": {
        "type": "detail",
        "value": "Start your book with .docx files"
      }
    }
  }
}

Placeholders and Empty States

Use placeholders to guide users when content is missing or not yet created:

{
  "new": {
    "type": "placeholder",
    "value": "Untitled chapter"
  }
}

Merge request reports