WordPress / openverse

Openverse is a search engine for openly-licensed media. This monorepo includes all application code.
https://openverse.org
MIT License
247 stars 199 forks source link

Make sure frontend opengraph and seo tags are translated #1129

Open zackkrida opened 1 year ago

zackkrida commented 1 year ago

Blocked by #4257

Problem

While reviewing #1100 I noticed that our default meta descriptions and titles aren't localized.

Description

These strings should be moved into en.json5 so they can be translated for all users.

Alternatives

Additional context

Blocked because it is much easier to implement this after Nuxt 3 migration.

AetherUnbound commented 4 months ago

I tried to give this a shot, and it seems more complicated than I initially expected! There appear to be 3 separate values we want to translate in the head: title, og:title, and og:description. Unfortunately, all of these are loaded in the nuxt.config.ts file, which means that I don't think we have any internationalization/translation functions available at that time to translate those strings. Here's where those values exist:

https://github.com/WordPress/openverse/blob/83ed9647e8b33dbb13b356f2c92f683041506534/frontend/nuxt.config.ts#L53

https://github.com/WordPress/openverse/blob/5e1d437086a16f27103ca4ae8cfdd9b582537809/frontend/src/constants/meta.ts#L27-L37

I paired with @dhruvkb and we tried to see what alternate approaches there were. We came across the following:

These suggested that we might be able to affect the default layout with useMeta which translates certain tags. Unfortunately, the following diff did not bring about any translated tags in the head of the site once the frontend was run:

diff --git a/frontend/nuxt.config.ts b/frontend/nuxt.config.ts
index 75a87f94a..5d801465c 100644
--- a/frontend/nuxt.config.ts
+++ b/frontend/nuxt.config.ts
@@ -50,7 +50,7 @@ const favicons = [

 // Default html head
 const head = {
-  title: "Openly Licensed Images, Audio and More | Openverse",
+  // title: "Openly Licensed Images, Audio and More | Openverse",
   meta,
   link: [
     ...favicons,
diff --git a/frontend/src/constants/meta.ts b/frontend/src/constants/meta.ts
index a1c3c2140..a6ce8ecaa 100644
--- a/frontend/src/constants/meta.ts
+++ b/frontend/src/constants/meta.ts
@@ -1,4 +1,5 @@
 const NUMBER_OF_RECORDS = "800 million"
+const NUMBER_OF_RECORDS_MILLIONS = 800
 const DESCRIPTION = `Search over ${NUMBER_OF_RECORDS} free and openly licensed images, photos, audio, and other media types for reuse and remixing.`

 /**
@@ -24,17 +25,17 @@ export const meta = [
     name: "description",
     content: DESCRIPTION,
   },
-  { hid: "og:title", property: "og:title", content: "Openverse" },
+  // { hid: "og:title", property: "og:title", content: "Openverse" },
   {
     hid: "og:image",
     property: "og:image",
     content: "/openverse-default.jpg",
   },
-  {
-    hid: "og:description",
-    name: "og:description",
-    content: DESCRIPTION,
-  },
+  // {
+  //   hid: "og:description",
+  //   name: "og:description",
+  //   content: DESCRIPTION,
+  // },
   { name: "twitter:card", content: "summary_large_image" },
   { name: "twitter:site", content: "@WPOpenverse" },
 ]
diff --git a/frontend/src/layouts/default.vue b/frontend/src/layouts/default.vue
index f78c54800..0aa269d3e 100644
--- a/frontend/src/layouts/default.vue
+++ b/frontend/src/layouts/default.vue
@@ -19,7 +19,9 @@
 </template>
 <script lang="ts">
 import { computed, defineComponent, onMounted } from "vue"
+import { useMeta } from "@nuxtjs/composition-api"

+import { useI18n } from "~/composables/use-i18n"
 import { useLayout } from "~/composables/use-layout"

 import { useUiStore } from "~/stores/ui"
@@ -44,6 +46,7 @@ export default defineComponent({
   },
   setup() {
     const uiStore = useUiStore()
+    const i18n = useI18n()

     const { updateBreakpoint } = useLayout()

@@ -59,6 +62,18 @@ export default defineComponent({
     const isDesktopLayout = computed(() => uiStore.isDesktopLayout)
     const breakpoint = computed(() => uiStore.breakpoint)

+    useMeta({
+      title: i18n.t('header.meta.title'),
+      meta: [
+        { hid: "og:title", property: "og:title", content: i18n.t('header.meta.ogTitle') },
+        {
+          hid: "og:description",
+          name: "og:description",
+          content: i18n.t('header.meta.ogDescription'),
+        }
+]
+    })
+
     return {
       isDesktopLayout,
       breakpoint,
diff --git a/frontend/src/locales/scripts/en.json5 b/frontend/src/locales/scripts/en.json5
index 9b93fa20f..03b498d60 100644
--- a/frontend/src/locales/scripts/en.json5
+++ b/frontend/src/locales/scripts/en.json5
@@ -61,6 +61,11 @@
       simple: "Menu",
       withCount: "Menu. {count} filter applied|Menu. {count} filters applied",
     },
+    meta: {
+      title: "Openly Licensed Images, Audio and More | {openverse}",
+      ogTitle: "{openverse}",
+      ogDescription: "Search over {count} million free and openly licensed images, photos, audio, and other media types for reuse and remixing."
+    }
   },
   navigation: {
     about: "About",

I looked into this because I thought it'd be a bit more straightforward, but it seems quite complex actually :sweat_smile: @obulat, do you have any insight or suggestions on how we might approach this, given it seems we need the app context in order to run translations (but that these values are created when the app context is being constructed)?

obulat commented 4 months ago

In Nuxt 3, we have a single entry-point, app.vue. We should add the translated descriptions and titles there, instead of trying to figure out how to use the i18n in the nuxt.config. Interesting how some things are much simpler after the migration :) I added a blocked label

obulat commented 2 months ago

This issue is now unblocked. We probably need to use https://nuxtseo.com/site-config/integrations/i18n for setting the title and description.