dashboards-search-relevance icon indicating copy to clipboard operation
dashboards-search-relevance copied to clipboard

[Refactoring] User-Facing Strings Should Be Wrapped

Open sejli opened this issue 1 year ago • 3 comments

Description

This has been brought to attention by this comment on a PR. We have many user-facing strings that are not wrapped for internalization. This is not consistent with OpenSearch Dashboards guidelines. User-facing strings should be updated to be compatible with the default message extraction tool.

OSD example usage

<EuiEmptyPrompt
          iconType="alert"
          iconColor="danger"
          title={
            <h2>
              <FormattedMessage
                id="core.application.appNotFound.title"
                defaultMessage="Application Not Found"
              />
            </h2>
          }
          body={
            <p>
              <FormattedMessage
                id="core.application.appNotFound.pageDescription"
                defaultMessage="No application was found at this URL. Try going back or choosing an app from the menu."
              />
            </p>
          }
        />

dashboards-search-relevance example of missing FormattedMessage

sejli avatar Oct 11 '23 22:10 sejli

@sejli I'd like to pick this up

nung22 avatar Oct 16 '23 20:10 nung22

Thanks for picking it up @nung22 !

noCharger avatar Oct 17 '23 17:10 noCharger

Notes for wrapping user-facing strings

Collection of resources for completing this task.

Procedures

I18n Provider

Translated components need to be wrapped by I18nProvider.

Before translation:

export const Flyout = () => {
  const { setShowFlyout } = useSearchRelevanceContext();

  return (
    <EuiFlyout>
      {...}
    </EuiFlyout>
  );
};

After translation:

import { I18nProvider, FormattedMessage } from '@osd/i18n/react';

export const Flyout = () => {
  const { setShowFlyout } = useSearchRelevanceContext();

  return (
    <I18nProvider>
      <EuiFlyout>
        {...}
      </EuiFlyout>
    </I18nProvider>
  );
};

Simple Message

Before translation:

<p>Add at least one query to display search results.</p>

After translation:

<p>
    <FormattedMessage
         id="searchRelevance.result.noQueryPrompt"
         defaultMessage="Add at least one query to display search results."
     />
</p>

Complex Message (contains other tags like OuiCode, OuiLink, and strong)

String should be divided with inner messages placed into the values property of FormattedMessage

Before translation:

<p>
  Enter a query in{' '}
  <EuiLink
    target="_blank"
    href="https://opensearch.org/docs/latest/opensearch/query-dsl/index/"
  >
    OpenSearch Query DSL
  </EuiLink>
  . Use the <EuiCode>%SearchText%</EuiCode> variable to refer to the text in the search
  bar. When you enter <strong>Search</strong>, the queries are sent to the search engine
  using the <EuiCode>GET</EuiCode> HTTP method and the <EuiCode>_search</EuiCode>{' '}
  endpoint.
</p>

After translation:

<p>
  <FormattedMessage
    id="searchRelevance.flyout.queryFormatDetail"
    defaultMessage="Enter a query in {queryDslLink}. Use the {variableName} variable to refer
    to the text in the search bar. When you enter {strongSearch}, the queries are sent to the search
    engine using the {methodName} HTTP method and the {endpointName} endpoint."
    values={{
      queryDslLink: (
        <EuiLink
          target="_blank"
          href="https://opensearch.org/docs/latest/opensearch/query-dsl/index/"
        >
          <FormattedMessage
            id="searchRelevance.flyout.queryFormatDetail.queryDslLinkLabel"
            defaultMessage="OpenSearch Query DSL"
          />
        </EuiLink>
      ),
      variableName: (
        <EuiCode>
          <FormattedMessage
            id="searchRelevance.flyout.queryFormatDetail.variableNameCodeLabel"
            defaultMessage="%SearchText%"
          />
        </EuiCode>
      ),
      strongSearch: (
        <strong>
          <FormattedMessage
            id="searchRelevance.flyout.queryFormatDetail.strongSearchLabel"
            defaultMessage="Search"
          />
        </strong>
      ),
      methodName: (
        <EuiCode>
          <FormattedMessage
            id="searchRelevance.flyout.queryFormatDetail.methodNameCodeLabel"
            defaultMessage="GET"
          />
        </EuiCode>
      ),
      endpointName: (
        <EuiCode>
          <FormattedMessage
            id="searchRelevance.flyout.queryFormatDetail.endpointNameCodeLabel"
            defaultMessage="_search"
          />
        </EuiCode>
      ),
    }}
  />
</p>

Unit Tests

Replace mount with shallow in the test file.

Before translation:

import { configure, mount } from 'enzyme';
const wrapper = mount(
  <SearchRelevanceContextProvider>
    <Flyout />
  </SearchRelevanceContextProvider>
);

After translation:

import { configure, shallow } from 'enzyme';
const wrapper = shallow(
  <SearchRelevanceContextProvider>
    <Flyout />
  </SearchRelevanceContextProvider>
);

Documentation

Similar Implementations in OSD

nung22 avatar Nov 08 '23 01:11 nung22

[Search Triage] @sejli Do you plan to take a look on this?

sandeshkr419 avatar Jan 08 '25 17:01 sandeshkr419

Haven't had bandwidth to take a look at dashboards-search-relevance improvements. It'll probably be later down the line when we revisit this.

sejli avatar Jan 10 '25 23:01 sejli