/**
  * {@inheritdoc}
  */
 public function readEntry($path, $locale, array $indices, $fallback = true)
 {
     $entry = null;
     $isMultiValued = false;
     $readSucceeded = false;
     $exception = null;
     $currentLocale = $locale;
     $testedLocales = array();
     while (null !== $currentLocale) {
         // Resolve any aliases to their target locales
         if (isset($this->localeAliases[$currentLocale])) {
             $currentLocale = $this->localeAliases[$currentLocale];
         }
         try {
             $data = $this->reader->read($path, $currentLocale);
             $currentEntry = RecursiveArrayAccess::get($data, $indices);
             $readSucceeded = true;
             $isCurrentTraversable = $currentEntry instanceof \Traversable;
             $isCurrentMultiValued = $isCurrentTraversable || is_array($currentEntry);
             // Return immediately if fallback is disabled or we are dealing
             // with a scalar non-null entry
             if (!$fallback || !$isCurrentMultiValued && null !== $currentEntry) {
                 return $currentEntry;
             }
             // =========================================================
             // Fallback is enabled, entry is either multi-valued or NULL
             // =========================================================
             // If entry is multi-valued, convert to array
             if ($isCurrentTraversable) {
                 $currentEntry = iterator_to_array($currentEntry);
             }
             // If previously read entry was multi-valued too, merge them
             if ($isCurrentMultiValued && $isMultiValued) {
                 $currentEntry = array_merge($currentEntry, $entry);
             }
             // Keep the previous entry if the current entry is NULL
             if (null !== $currentEntry) {
                 $entry = $currentEntry;
             }
             // If this or the previous entry was multi-valued, we are dealing
             // with a merged, multi-valued entry now
             $isMultiValued = $isMultiValued || $isCurrentMultiValued;
         } catch (ResourceBundleNotFoundException $e) {
             // Continue if there is a fallback locale for the current
             // locale
             $exception = $e;
         } catch (OutOfBoundsException $e) {
             // Remember exception and rethrow if we cannot find anything in
             // the fallback locales either
             $exception = $e;
         }
         // Remember which locales we tried
         $testedLocales[] = $currentLocale;
         // Check whether fallback is allowed
         if (!$fallback) {
             break;
         }
         // Then determine fallback locale
         $currentLocale = Locale::getFallback($currentLocale);
     }
     // Multi-valued entry was merged
     if ($isMultiValued) {
         return $entry;
     }
     // Entry is still NULL, but no read error occurred
     if ($readSucceeded) {
         return $entry;
     }
     // Entry is still NULL, read error occurred. Throw an exception
     // containing the detailed path and locale
     $errorMessage = sprintf('Couldn\'t read the indices [%s] for the locale "%s" in "%s".', implode('][', $indices), $locale, $path);
     // Append fallback locales, if any
     if (count($testedLocales) > 1) {
         // Remove original locale
         array_shift($testedLocales);
         $errorMessage .= sprintf(' The indices also couldn\'t be found for the fallback locale(s) "%s".', implode('", "', $testedLocales));
     }
     throw new MissingResourceException($errorMessage, 0, $exception);
 }
 private function generateFallbackMapping(array $displayLocales, array $aliases)
 {
     $mapping = array();
     foreach ($displayLocales as $displayLocale => $_) {
         $mapping[$displayLocale] = null;
         $fallback = $displayLocale;
         // Recursively search for a fallback locale until one is found
         while (null !== ($fallback = Locale::getFallback($fallback))) {
             // Currently, no locale has an alias as fallback locale.
             // If this starts to be the case, we need to add code here.
             assert(!isset($aliases[$fallback]));
             // Check whether the fallback exists
             if (isset($displayLocales[$fallback])) {
                 $mapping[$displayLocale] = $fallback;
                 break;
             }
         }
     }
     return $mapping;
 }