translation.html.twig 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. {% extends '@WebProfiler/Profiler/layout.html.twig' %}
  2. {% import _self as helper %}
  3. {% block toolbar %}
  4. {% if collector.messages|length %}
  5. {% set icon %}
  6. {{ include('@WebProfiler/Icon/translation.svg') }}
  7. {% set status_color = collector.countMissings ? 'red' : collector.countFallbacks ? 'yellow' %}
  8. {% set error_count = collector.countMissings + collector.countFallbacks %}
  9. <span class="sf-toolbar-value">{{ error_count ?: collector.countDefines }}</span>
  10. {% endset %}
  11. {% set text %}
  12. <div class="sf-toolbar-info-piece">
  13. <b>Default locale</b>
  14. <span class="sf-toolbar-status">
  15. {{ collector.locale|default('-') }}
  16. </span>
  17. </div>
  18. <div class="sf-toolbar-info-piece">
  19. <b>Missing messages</b>
  20. <span class="sf-toolbar-status sf-toolbar-status-{{ collector.countMissings ? 'red' }}">
  21. {{ collector.countMissings }}
  22. </span>
  23. </div>
  24. <div class="sf-toolbar-info-piece">
  25. <b>Fallback messages</b>
  26. <span class="sf-toolbar-status sf-toolbar-status-{{ collector.countFallbacks ? 'yellow' }}">
  27. {{ collector.countFallbacks }}
  28. </span>
  29. </div>
  30. <div class="sf-toolbar-info-piece">
  31. <b>Defined messages</b>
  32. <span class="sf-toolbar-status">{{ collector.countDefines }}</span>
  33. </div>
  34. {% endset %}
  35. {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, status: status_color }) }}
  36. {% endif %}
  37. {% endblock %}
  38. {% block menu %}
  39. <span class="label label-status-{{ collector.countMissings ? 'error' : collector.countFallbacks ? 'warning' }} {{ collector.messages is empty ? 'disabled' }}">
  40. <span class="icon">{{ include('@WebProfiler/Icon/translation.svg') }}</span>
  41. <strong>Translation</strong>
  42. {% if collector.countMissings or collector.countFallbacks %}
  43. {% set error_count = collector.countMissings + collector.countFallbacks %}
  44. <span class="count">
  45. <span>{{ error_count }}</span>
  46. </span>
  47. {% endif %}
  48. </span>
  49. {% endblock %}
  50. {% block panel %}
  51. <h2>Translation</h2>
  52. <div class="metrics">
  53. <div class="metric">
  54. <span class="value">{{ collector.locale|default('-') }}</span>
  55. <span class="label">Default locale</span>
  56. </div>
  57. <div class="metric">
  58. <span class="value">{{ collector.fallbackLocales|join(', ')|default('-') }}</span>
  59. <span class="label">Fallback locale{{ collector.fallbackLocales|length != 1 ? 's' }}</span>
  60. </div>
  61. </div>
  62. <h2>Messages</h2>
  63. {% if collector.messages is empty %}
  64. <div class="empty">
  65. <p>No translations have been called.</p>
  66. </div>
  67. {% else %}
  68. {% block messages %}
  69. {# sort translation messages in groups #}
  70. {% set messages_defined, messages_missing, messages_fallback = [], [], [] %}
  71. {% for message in collector.messages %}
  72. {% if message.state == constant('Symfony\\Component\\Translation\\DataCollectorTranslator::MESSAGE_DEFINED') %}
  73. {% set messages_defined = messages_defined|merge([message]) %}
  74. {% elseif message.state == constant('Symfony\\Component\\Translation\\DataCollectorTranslator::MESSAGE_MISSING') %}
  75. {% set messages_missing = messages_missing|merge([message]) %}
  76. {% elseif message.state == constant('Symfony\\Component\\Translation\\DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK') %}
  77. {% set messages_fallback = messages_fallback|merge([message]) %}
  78. {% endif %}
  79. {% endfor %}
  80. <div class="sf-tabs">
  81. <div class="tab {{ collector.countMissings == 0 ? 'active' }}">
  82. <h3 class="tab-title">Defined <span class="badge">{{ collector.countDefines }}</span></h3>
  83. <div class="tab-content">
  84. <p class="help">
  85. These messages are correctly translated into the given locale.
  86. </p>
  87. {% if messages_defined is empty %}
  88. <div class="empty">
  89. <p>None of the used translation messages are defined for the given locale.</p>
  90. </div>
  91. {% else %}
  92. {% block defined_messages %}
  93. {{ helper.render_table(messages_defined) }}
  94. {% endblock %}
  95. {% endif %}
  96. </div>
  97. </div>
  98. <div class="tab">
  99. <h3 class="tab-title">Fallback <span class="badge {{ collector.countFallbacks ? 'status-warning' }}">{{ collector.countFallbacks }}</span></h3>
  100. <div class="tab-content">
  101. <p class="help">
  102. These messages are not available for the given locale
  103. but Symfony found them in the fallback locale catalog.
  104. </p>
  105. {% if messages_fallback is empty %}
  106. <div class="empty">
  107. <p>No fallback translation messages were used.</p>
  108. </div>
  109. {% else %}
  110. {% block fallback_messages %}
  111. {{ helper.render_table(messages_fallback, true) }}
  112. {% endblock %}
  113. {% endif %}
  114. </div>
  115. </div>
  116. <div class="tab {{ collector.countMissings > 0 ? 'active' }}">
  117. <h3 class="tab-title">Missing <span class="badge {{ collector.countMissings ? 'status-error' }}">{{ collector.countMissings }}</span></h3>
  118. <div class="tab-content">
  119. <p class="help">
  120. These messages are not available for the given locale and cannot
  121. be found in the fallback locales. Add them to the translation
  122. catalogue to avoid Symfony outputting untranslated contents.
  123. </p>
  124. {% if messages_missing is empty %}
  125. <div class="empty">
  126. <p>There are no messages of this category.</p>
  127. </div>
  128. {% else %}
  129. {% block missing_messages %}
  130. {{ helper.render_table(messages_missing) }}
  131. {% endblock %}
  132. {% endif %}
  133. </div>
  134. </div>
  135. </div>
  136. <script>Sfjs.createFilters();</script>
  137. {% endblock messages %}
  138. {% endif %}
  139. {% endblock %}
  140. {% macro render_table(messages, is_fallback) %}
  141. <table data-filters>
  142. <thead>
  143. <tr>
  144. <th data-filter="locale">Locale</th>
  145. {% if is_fallback %}
  146. <th>Fallback locale</th>
  147. {% endif %}
  148. <th data-filter="domain">Domain</th>
  149. <th>Times used</th>
  150. <th>Message ID</th>
  151. <th>Message Preview</th>
  152. </tr>
  153. </thead>
  154. <tbody>
  155. {% for message in messages %}
  156. <tr data-filter-locale="{{ message.locale }}" data-filter-domain="{{ message.domain }}">
  157. <td class="font-normal text-small nowrap">{{ message.locale }}</td>
  158. {% if is_fallback %}
  159. <td class="font-normal text-small nowrap">{{ message.fallbackLocale|default('-') }}</td>
  160. {% endif %}
  161. <td class="font-normal text-small text-bold nowrap">{{ message.domain }}</td>
  162. <td class="font-normal text-small nowrap">{{ message.count }}</td>
  163. <td>
  164. <span class="nowrap">{{ message.id }}</span>
  165. {% if message.transChoiceNumber is not null %}
  166. <small class="newline">(pluralization is used)</small>
  167. {% endif %}
  168. {% if message.parameters|length > 0 %}
  169. <button class="btn-link newline text-small sf-toggle" data-toggle-selector="#parameters-{{ loop.index }}" data-toggle-alt-content="Hide parameters">Show parameters</button>
  170. <div id="parameters-{{ loop.index }}" class="hidden">
  171. {% for parameters in message.parameters %}
  172. {{ profiler_dump(parameters, maxDepth=1) }}
  173. {% endfor %}
  174. </div>
  175. {% endif %}
  176. </td>
  177. <td class="prewrap">{{ message.translation }}</td>
  178. </tr>
  179. {% endfor %}
  180. </tbody>
  181. </table>
  182. {% endmacro %}