Select with fallback and default?
Well this was fun. Usually I control language strings in the application layer rather than the database, but this was a good opportunity to learn how to use WITH RECURSIVE.
First let's define the tables that will be used: locale and dictionary:
CREATE TABLE locale (
    code           varchar(6)     NOT NULL    ,
    description    varchar(64)    NOT NULL    ,
    fallback       varchar(6)         NULL    ,
    PRIMARY KEY (code)
);


CREATE TABLE dictionary (
    id             serial         NOT NULL    ,
    key            varchar(64)    NOT NULL    ,
    value          varchar(128)   NOT NULL    ,
    locale_code    varchar(6)     NOT NULL    ,
    PRIMARY KEY (id)
);

There should be no surprises here. Locale's code can be 6 characters in length, though it will generally be either 2 or 5. If the fallback is NULL, then the record is considered &quot;top level&quot;. This will allow you to have multiple top levels if you so choose, as you will see in the examples below.
Next, let's populate these tables:
INSERT INTO locale (&quot;code&quot;, &quot;description&quot;, &quot;fallback&quot;)
VALUES ('en-us', 'English (US)', NULL), ('en-gb', 'English (UK)', 'en-us'), ('en-ca', 'English (Canadian)', 'en-gb'),
       ('fr-fr', 'French (France)', 'en-us'), ('fr-be', 'French (Belgium)', 'fr-fr'), ('fr-ca', 'French (Quebec)', 'fr-fr'),
       ('nl-nl', 'Dutch', 'en-us'), ('nl-be', 'Dutch (Belgium)', 'nl-nl'), ('ja-jp', 'Japanese', 'en-us'),
       ('es-es', 'Spanish', NULL), ('es-ar', 'Spanish (Argentina)', 'es-es'), ('es-bo', 'Spanish (Bolivia)', 'es-es'),
       ('es-cl', 'Spanish (Chile)', 'es-bo'), ('es-sv', 'Spanish (El Salvador)', 'es-cl'), ('es-mx', 'Spanish (Mexico)', 'es-cl');

INSERT INTO dictionary (key, value, locale_code)
VALUES ('yes_button', 'Yes', 'en-us'), ('yes_button', 'Very Well', 'en-gb'), ('yes_button', 'Sorry, Yes', 'en-ca'),
       ('yes_button', 'Oui', 'fr-fr'), ('yes_button', 'C''est exact', 'fr-ca'), 
       ('yes_button', 'Ja', 'nl-nl'), ('yes_button', 'はい', 'ja-jp'),
       ('yes_button', 'Sí', 'es-es'), ('yes_button', 'Absolutamente', 'es-bo'), ('yes_button', 'Por favor', 'es-sv');

Note:These translations are not at all accurate, but instead intended to show how the final query works and how you might tweak it.
And now the SQL Query:
WITH RECURSIVE c AS (SELECT 1 as level, code, fallback FROM locale WHERE code = 'nl-be'
                      UNION ALL 
                     SELECT c.level + 1 as level, lo.code, lo.fallback
                       FROM locale lo JOIN c ON c.fallback = lo.code)
SELECT c.level, c.code, dic.key, dic.value
  FROM c LEFT OUTER JOIN dictionary dic ON c.code = dic.locale_code WHERE dic.key = 'yes_button'
 ORDER BY c.level;

The target language you seek is in WHERE code = 'nl-be', and the dictionary key is within the OUTER JOIN with WHERE dic.key = 'yes_button'.
If you run this, you will receive the following results:
level | code  | key        | value
----- | ----- | ---------- | -----
2     | nl-nl | yes_button | Ja
3     | en-us | yes_button | Yes

Because there is no value for nl-be, the next value is returned. If there is no value for that one, en-us will be returned.
You can see this in action with Spanish as well. Change the language to es-sv and results will come back for three options.
level | code  | key        | value
----- | ----- | ---------- | -----
1     | es-sv | yes_button | Por favor
3     | es-bo | yes_button | Absolutamente
4     | es-es | yes_button | Sí

Note that there is no en-us in the output, nor is there any record for &quot;level&quot; 2. This is because es-es does not have a fallback, and there is no matching dictionary entry for es-cl, so it is excluded.
If this works for you, remember to set LIMIT 1 at the end of the SQL query so that you are given just the most relevant value.

Big hat-tip to Laurenz Albe for his many, many examples of how to write RECURSIVE queries across Stack Exchange. I learned something new and (hopefully) solved a problem today.