PHP Bilingual Error System Ideas
I have had this problem several times and have tried different solutions. This is my current solution.

I use an associative array as a key-value list of message strings. Then I set the errors to a specific key name and fetch the corresponding message in a appropriately named file like english.php etc. This file can be all types of formats, but I will stick with PHP. 

This has two main advantages:


Human readable key names
A central place all message string are stored, which in turn makes reuse of messages easier.


An example would be:

/*
* File: english.php
* This must return an associative array. This array can be multidimentional to better
* group different messages.
*/
$lang = [];
$lang['field_required'] = 'The field is required.';
$lang['success'] = 'The post was successfully created.';

// A grouped entry.
$lang['registration']['email_unavailable'] = 'The provided email is already in use.';

/*
 * A message string that requires some input that cannot be determined beforehand can 
 * be solved by using the sprintf() or vsprintf() functions with the latter using an
 * array as an argument.
 */
$lang['shopping']['cart']['items']['amount_of_items'] = 'There are %d item(s) in your shopping cart.';

return $lang;

/*
 * File: bootstrapper.php (example)
 * 
 * Some centrally available file. The $languages variable should be provided to
 * classes using dependency injection or made available otherwise.
 */
$current_language = 'english'; // Detected in a class or some other code.

$file = "path/to/language/{$current_language}.php"; // This file must return an array.

/*
 * Include the currently supported language file.
 * You can also make a list of supported languages before trying to load the file.
 */
if(!is_file($file) || !is_readable($file)) {
    // Do something here...
}

$languages = include $file;

/* 
 * (OPTIONAL)
 * Here you can check if the language file returned the expected format. 
 * Example: if(!is_array($languages)) { // do something }
 */

/*
 * Some model or controller (if you're validating input before sending it to the
 * model).
 * Here the language key is the same for all languages and only the value is 
 * different.
 */
 $field_id = 'username';
 $field = filter_input(INPUT_POST, $field_id, FILTER_SANITIZE_STRING); // Just as good practice

 if(!check_required_field_function($field)) {
     $errors[$field_id] = $languages['field_required'];
 }

 /*
  * File: some view.php
  * Since this file properly contains some HTML I have used an alternative PHP syntax
  */
 &lt;?php if(isset($errors) &amp;&amp; !empty($errors)): ?&gt;

     &lt;p&gt;The following errors occurred.&lt;/p&gt;
     &lt;ul&gt;         

     &lt;?php foreach($errors as $error): ?&gt;

         &lt;li&gt;&lt;?php echo htmlspecialchars($error, ENT_QUOTES, 'UTF-8'); ?&gt;&lt;/li&gt; 

     &lt;? endforeach; ?&gt;

     &lt;/ul&gt;

 &lt;?php endif; ?&gt;


The output escaping isn't stictly related to this question, but I added it as good practice.

This approach can properly be refactored a lot. Please let me know if you have any questions or something you would point out.

This is a very simple outline of the strategy I use. Hope it helps.