I feel that the answers when you search on the web for this problem are not clear enough so I want to make a compilation of the steps I follow to achieve this.
When I write "interface translations" I refer to those strings written always in English (even when the site we are developing has no English enabled) that are typically surrounded by a t() function, a twig trans filter or are part of some yml definition like module_name.links.menu.yml. For translating configuration the process is quite different.
The main page for information about this is the Drupal API page and its comments, but the comments are not shared among the different versions of that page so some information gets a bit sunk as new minor versions of Drupal core are released.
Let’s do an example with two strings we have in our code that are enclosed in a t() function.
t(‘My custom string’)
t(‘Every last Thursday of the month at 20:00 in @location’)
The first step is to add two lines more to our example_event.info.yml file like this:
name: Example event
description: Functionality related with the date the event happens
'interface translation project': example_event
'interface translation server pattern': 'modules/custom/example_event/translations/%language.po'
This way we are telling Drupal to look into the translations directory of the custom module for files named like "es.po" or whatever is the language code we are translating to.
Files with the .po extension are in the gettext format so it will look like this:
"Project-Id-Version: Example event\n"
"Content-Type: text/plain; charset=utf-8\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
msgid "My custom string"
msgstr "Mi cadena personalizada"
msgid "Every last Thursday of the month at 20:00 in @location"
msgstr "Todos los últimos jueves de mes en @location a las 20:00"
Then we can commit this file into the version control system to keep track of changes.
Drupal string translations live in the database, not in files, so in order to update the database we need two commands:
To check for new translations (contrib modules will be checked also):
To store the translated strings in the database based on the .po files.
Add these two drush commands to your deployment/CI to have the interface translated.
This is tested on Drupal 8.5.x but I don't think compatibility for this will be removed.
You can use the potx module to scan your code to look for translatable strings instead of creating your .po file manually. The potx module runs on Drupal 7 but there is a heavily patched Drupal 8 version to be able to run it within your installation.
So that is pretty much everything you need to know to translate from .po files. In general I think the process can be changed to require less code for example: any “translations” folder should be auto-discovered for translations. There is issues open about this subject if you want to add your ideas.