How can I extend Linguify for language-dependent images? - Converting linguify context to string

Dear @SillyFreak and @bluss ,

Your suggestions about #context do-something(linguify(...)) and #context image(linguify("flag_logo")) were exactly what I needed to get on the right track.

Building on that, I’ve created a solution by wrapping linguify within my own set of functions. This allows me to read the TOML file, update both my custom state database and the linguify database, and then call my own functions within the Typst context.

Here’s the code I’ve put into linguifyPicture.typ:

#import "@preview/linguify:0.4.2": set-database as linguify-set-database

#let language-database = state("language-database", none)

#let set-language-database(data) = {
  language-database.update(data)
}

#let get-current-language = () => text.lang

#let load-lang(data) = {
  linguify-set-database(data) // Set the database for the @preview/linguify package
  set-language-database(data) // Set the database for our standalone localized-image function
}

#let get-localized-path(key, current-lang) = {
  let lang-data = language-database.get()
  if lang-data == none {
    panic("Language database not set. Call `load-lang()` at the beginning of your document.")
    return none
  }

  let path = none
  let lang-section-name = current-lang

  if lang-section-name in lang-data.lang {
    let lang-section = lang-data.lang.at(lang-section-name)
    if key in lang-section {
      path = lang-section.at(key)
    }
  }

  if path == none and "default-lang" in lang-data.conf {
    let default-lang = lang-data.conf.at("default-lang")
    let default-lang-section-name = "lang." + default-lang
    if default-lang-section-name in lang-data.lang {
      let default-lang-section = lang-data.lang.at(default-lang-section-name)
      path = default-lang-section.at(key, default: none)
    }
  }

  path
}

#let localized-image(key, ..args) = {
  let current-lang = get-current-language()
  let nicePath = get-localized-path(key, current-lang)
  if not nicePath.starts-with("/") and nicePath != none {
    nicePath = "/" + nicePath
  }
  if nicePath != "badPath" {
    image(nicePath, ..args)
  } else {
    panic("Image key '" + key + "' not found for language '" + current-lang + "'.")
  }
}

I am not sure the code above is bulletproof… Here’s how I’m using it in main.typ:

#import "@preview/linguify:0.4.2": * 
#import "Tools/linguifyPicture/linguifyPicture.typ": load-lang, localized-image

#set text(lang: "de")

#let lang-data = toml("Cover/translations.toml")

#load-lang(lang-data) //updates both linguify and linguifyPicture database

#context localized-image("flag_logo", /*image arguments here*/)

One thing I discovered is that Typst doesn’t seem to have built-in support for webp images, so I had to update my TOML file to use .png extensions instead (e.g., "Cover/Pictures/Flag_of_Germany.webp" became "Cover/Pictures/Flag_of_Germany.png").

Thanks again for your helpful insights! This approach seems to be working for my needs.

2 Likes