This is how i18n typically works in code:
Developers write the strings in English (or their native language), but mark all the strings with a function/macro which identifies them for translation. In C++ this might be _("blah") or tr("blah") — something which is short and easy to write.
A tool (which may be integrated into the build system), extracts all the strings marked for translation into a big list of translatable strings. This list is then provided to the translators, who do not need to be developers or compile the code themselves. They just create a translation for each listed string and send back a file in the appropriate format (which may or may not be created with the help of translation tools, perhaps with a GUI).
At runtime, the code looks up each translatable string, finds the corresponding translated string in the chosen language, and shows the translated version.
At no point do developers (who in this case would be mission authors) have to mess around with manually choosing string IDs. All they do is use the appropriate function/macro/syntax to mark particular strings as translatable. String IDs may be used internally but are completely invisible to developers.
I suggest that any system that involves instructions like "search the list of known strings for a similar string" or "manually choose a string ID between 20000 and 89999 and then write it as #str_23456" are over-complicated, un-ergonomic and doomed to be largely ignored by mappers.