Multilingual FileMaker solutions — DDRparser + ACF-plugin: the ultimate combo

With ACF-plugin 1.7.6.2 we’ve introduced new functions for fast, clean translations. Paired with DDRparser 1.2.0, you can scan a solution for translatable strings, generate a POT file, translate it with Poedit (or any PO platform/AI), and load the resulting .po back into your FileMaker app from a container field or a file path. That’s it — translations live!

The DDRparser GUI tool shipped with v1.2.0 also doubles as a demo of this technique.

Note: We have lifted the license requirements for the translation lookup functions «_(some text)» in version 1.7.6.1+, for users running demo mode it should not break application functioning when demo window expires.

Here is the manual page for the new functions: https://horneks.no/manuals/ACF/translationfunctions.html


Why not the traditional approaches?

Developers have tried many patterns for multi-language in FileMaker. They work, but they don’t scale well:

  • A table full of global fields (one per string) — becomes impossible to navigate as strings grow.
  • Global variables rendered in layouts — hard to discover/maintain; clutters the Data Viewer.
  • Duplicate layouts per language — reliable, but a maintenance burden (every change × languages).
  • Lookup by key in a translations table — workable, but still more plumbing and upkeep.

The new flow (simple and professional)

1) Author strings inline

Use short, readable calls where the text lives:

_("My orders")
_("Overwrite file “%1”?" ; Packages::FileName)
_n("%1 item" ; "%1 items" ; Items::Count ; Items::Count)
  • %1, %2, … are placeholders (substituted at runtime).
  • _n picks singular/plural based on count (simple rule today; PO plural rules later).

2) Extract strings into a POT

Run DDRparser 1.2.0 to scan for _("…")/_n("…") calls and write TranslationFiles/messages.pot.

3) Translate with PO tools

Open the POT in Poedit (or any PO platform) and create one .po per language. Translate only msgstr — placeholders stay intact.

4) Load the translation at runtime

In your FileMaker app, load a .po from a container or disk:

  • ACF_Load_TranslationPO( Languages::POContainer )
  • or ACF_Load_TranslationPO( Get ( DocumentsPath ) & "i18n/en.po" )

If a string is missing, the original text is shown (safe fallback). You can also call ACF_UpdatePOT ( pathTo/messages.pot ) to append any runtime “misses” to the POT.


Built-in demo

The DDRparser GUI tool shipped with v1.2.0 demonstrates the full loop. It can also install/update the correct ACF-plugin if needed.


Layout text is now easy (FileMaker 20+)

Under the Text toolbar, choose Layout Calculation and just write:

_("My orders")

No more hunting through fields or variables — the string is right where it’s used.


What makes this better?

  • Readable source — text is inline: _("…").
  • Automatic extraction — DDRparser creates a clean POT.
  • Professional workflow — standard PO format; use Poedit, Weblate, POEditor, etc.
  • Instant runtime — hash-map lookups keep translations equally fast, no matter how many strings you have.
  • Effortless iteration — new strings appear in the base language; update POT, translate, reload.

Quick start in your app

  1. Create a Languages table with:
    • Name (text)
    • PO (container)
  2. Script switchLanguage:
    • ACF_Clear_Translation
    • ACF_Load_TranslationPO ( Languages::PO )
  3. Add a dropdown of available languages on your main layout, add a script trigger to call switchLanguage — watch text update instantly.

Notes & tips

  • Prefer placeholders over string concatenation (e.g., “%1” for filenames).
  • Keep msgids tidy (no stray spaces; fix typos early).
  • Locale headers: Language: nb, Language: ja, etc. Add Plural-Forms (e.g., nb: nplurals=2; plural=(n != 1);, ja: nplurals=1; plural=0;).
  • For collaboration, PO is universal — Poedit, Weblate, POEditor, Crowdin, Lokalise all work.

Performance metrix

Tested on a Mac-Mini Intel Core i7, 3.2GHz, 32GB RAM. All strings have english original and norwegian translation. The .mo file is compiled .po file (in Poedit) – dropped the .mo file into the po-container instead. Way faster load time.

Number of Strings in containerLoad (po-container) – One timeLoad .mo file in po-container – insteadString lookup
1000.60 ms0.43 ms0.12 ms
1,0002.37 ms1.43 ms0.15 ms
10,00013.1 ms5 ms0.155 ms
100,000141 ms71 ms0.16 ms
500,000615 ms234 ms0.15 ms

Takeaway: load time scales linearly with catalog size, while lookup stays flat (~0.12–0.16 ms) regardless of size.

For a layout containing 50 translateable strings: average of 7.5 ms to translate the strings. Hardly noticable for the user.

Download & try

Grab DDRparser 1.2.0, run an extraction, translate with Poedit, and load the .po via the ACF-plugin 1.7.6.0. You’ll have a multilingual solution up and running in minutes — with a workflow that scales.

You may also like...