private static void getTranslatableStringsFromLevel(
      final Level level,
      final List<StringToCSNodeCollection> translationStrings,
      final boolean allowDuplicates) {
    if (level == null || translationStrings == null) return;

    addTranslationToNodeDetailsToCollection(
        level.getTitle(), level, allowDuplicates, translationStrings);

    final List<Level> levels = level.getChildLevels();
    for (final Level childLevel : levels) {
      getTranslatableStringsFromLevel(childLevel, translationStrings, allowDuplicates);
    }
  }
  @SuppressWarnings({"unchecked", "rawtypes"})
  public static void replaceTranslatedStrings(
      final ContentSpec contentSpec, final Map<String, String> translations) {
    if (contentSpec == null || translations == null || translations.size() == 0) return;

    /*
     * Get the translation strings and the nodes that the string maps to. We
     * assume that the text being provided here is an exact match for the
     * text that was supplied to getTranslatableStrings originally, which we
     * then assume matches the strings supplied as the keys in the
     * translations parameter.
     */
    final List<StringToCSNodeCollection> stringToNodeCollections =
        getTranslatableStrings(contentSpec, false);

    if (stringToNodeCollections == null || stringToNodeCollections.size() == 0) return;

    for (final StringToCSNodeCollection stringToNodeCollection : stringToNodeCollections) {
      final String originalString = stringToNodeCollection.getTranslationString();
      final ArrayList<ArrayList<Node>> nodeCollections =
          stringToNodeCollection.getNodeCollections();

      if (nodeCollections != null && nodeCollections.size() != 0) {
        /* Zanata will change the format of the strings that it returns. Here we account for any trimming that was done. */
        final ZanataStringDetails fixedStringDetails =
            new ZanataStringDetails(translations, originalString);
        if (fixedStringDetails.getFixedString() != null) {
          if (translations.containsKey(fixedStringDetails.getFixedString())) {
            final String translation = translations.get(fixedStringDetails.getFixedString());

            /* Build up the padding that Zanata removed */
            final StringBuilder leftTrimPadding = new StringBuilder();
            final StringBuilder rightTrimPadding = new StringBuilder();

            for (int i = 0; i < fixedStringDetails.getLeftTrimCount(); ++i)
              leftTrimPadding.append(" ");

            for (int i = 0; i < fixedStringDetails.getRightTrimCount(); ++i)
              rightTrimPadding.append(" ");

            final String fixedTranslation =
                leftTrimPadding.toString() + translation + rightTrimPadding.toString();

            for (final ArrayList<Node> nodes : nodeCollections) {
              if (nodes != null && nodes.size() != 0) {
                for (final Node node : nodes) {
                  if (node instanceof Level) {
                    ((Level) node).setTitle(fixedTranslation);
                  } else if (node instanceof KeyValueNode) {
                    ((KeyValueNode) node).setValue(fixedTranslation);
                  }
                }
              }
            }
          }
        }
      }
    }
  }