]> Untitled Git - lemmy-ui.git/commitdiff
Fix I18 next circular reference
authorSleeplessOne1917 <abias1122@gmail.com>
Thu, 22 Jun 2023 00:54:35 +0000 (20:54 -0400)
committerSleeplessOne1917 <abias1122@gmail.com>
Thu, 22 Jun 2023 00:54:35 +0000 (20:54 -0400)
70 files changed:
src/client/index.tsx
src/shared/components/app/app.tsx
src/shared/components/app/error-page.tsx
src/shared/components/app/footer.tsx
src/shared/components/app/navbar.tsx
src/shared/components/comment/comment-form.tsx
src/shared/components/comment/comment-node.tsx
src/shared/components/comment/comment-report.tsx
src/shared/components/common/badges.tsx
src/shared/components/common/comment-sort-select.tsx
src/shared/components/common/data-type-select.tsx
src/shared/components/common/emoji-picker.tsx
src/shared/components/common/html-tags.tsx
src/shared/components/common/icon.tsx
src/shared/components/common/image-upload-form.tsx
src/shared/components/common/language-select.tsx
src/shared/components/common/listing-type-select.tsx
src/shared/components/common/markdown-textarea.tsx
src/shared/components/common/moment-time.tsx
src/shared/components/common/navigation-prompt.tsx
src/shared/components/common/paginator.tsx
src/shared/components/common/registration-application.tsx
src/shared/components/common/searchable-select.tsx
src/shared/components/common/sort-select.tsx
src/shared/components/community/communities.tsx
src/shared/components/community/community-form.tsx
src/shared/components/community/community.tsx
src/shared/components/community/create-community.tsx
src/shared/components/community/sidebar.tsx
src/shared/components/home/admin-settings.tsx
src/shared/components/home/emojis-form.tsx
src/shared/components/home/home.tsx
src/shared/components/home/instances.tsx
src/shared/components/home/legal.tsx
src/shared/components/home/login.tsx
src/shared/components/home/rate-limit-form.tsx
src/shared/components/home/setup.tsx
src/shared/components/home/signup.tsx
src/shared/components/home/site-form.tsx
src/shared/components/home/site-sidebar.tsx
src/shared/components/home/tagline-form.tsx
src/shared/components/modlog.tsx
src/shared/components/person/cake-day.tsx
src/shared/components/person/inbox.tsx
src/shared/components/person/password-change.tsx
src/shared/components/person/profile.tsx
src/shared/components/person/registration-applications.tsx
src/shared/components/person/reports.tsx
src/shared/components/person/settings.tsx
src/shared/components/person/verify-email.tsx
src/shared/components/post/create-post.tsx
src/shared/components/post/metadata-card.tsx
src/shared/components/post/post-form.tsx
src/shared/components/post/post-listing.tsx
src/shared/components/post/post-listings.tsx
src/shared/components/post/post-report.tsx
src/shared/components/post/post.tsx
src/shared/components/private_message/create-private-message.tsx
src/shared/components/private_message/private-message-form.tsx
src/shared/components/private_message/private-message-report.tsx
src/shared/components/private_message/private-message.tsx
src/shared/components/search.tsx
src/shared/services/HttpService.ts
src/shared/services/I18NextService.ts [moved from src/shared/i18next.ts with 53% similarity]
src/shared/services/UserService.ts
src/shared/services/index.ts
src/shared/toast.ts
src/shared/utils/app/initialize-site.ts
src/shared/utils/app/update-community-block.ts
src/shared/utils/app/update-person-block.ts

index 4ff794eca850952e590632da944e79d8070d0a85..eb2bb80fe2e515221d127d6a5a2f62c179884b5a 100644 (file)
@@ -2,7 +2,7 @@ import { initializeSite } from "@utils/app";
 import { hydrate } from "inferno-hydrate";
 import { Router } from "inferno-router";
 import { App } from "../shared/components/app/app";
-import { HistoryService } from "../shared/services/HistoryService";
+import { HistoryService } from "../shared/services";
 
 import "bootstrap/js/dist/collapse";
 import "bootstrap/js/dist/dropdown";
index e615bb3a4fe8466a118210979f2f416481e8e54d..e50a70709fe572116e150315f2cf7ca2f316374d 100644 (file)
@@ -2,9 +2,9 @@ import { isAuthPath, setIsoData } from "@utils/app";
 import { Component, RefObject, createRef, linkEvent } from "inferno";
 import { Provider } from "inferno-i18next-dess";
 import { Route, Switch } from "inferno-router";
-import { i18n } from "../../i18next";
 import { IsoDataOptionalSite } from "../../interfaces";
 import { routes } from "../../routes";
+import { I18NextService } from "../../services";
 import AuthGuard from "../common/auth-guard";
 import ErrorGuard from "../common/error-guard";
 import { ErrorPage } from "./error-page";
@@ -31,13 +31,13 @@ export class App extends Component<any, any> {
 
     return (
       <>
-        <Provider i18next={i18n}>
+        <Provider i18next={I18NextService.i18n}>
           <div id="app" className="lemmy-site">
             <a
               className="skip-link bg-light text-dark p-2 text-decoration-none position-absolute start-0 z-3"
               onClick={linkEvent(this, this.handleJumpToContent)}
             >
-              ${i18n.t("jump_to_content", "Jump to content")}
+              ${I18NextService.i18n.t("jump_to_content", "Jump to content")}
             </a>
             {siteView && (
               <Theme defaultTheme={siteView.local_site.default_theme} />
index 7d4e297053eca00021d7c14366f6167b5112373c..ec352d4288dfeefbe628169b379e0b422575ec7a 100644 (file)
@@ -2,8 +2,8 @@ import { setIsoData } from "@utils/app";
 import { Component } from "inferno";
 import { T } from "inferno-i18next-dess";
 import { Link } from "inferno-router";
-import { i18n } from "../../i18next";
 import { IsoDataOptionalSite } from "../../interfaces";
+import { I18NextService } from "../../services";
 
 export class ErrorPage extends Component<any, any> {
   private isoData: IsoDataOptionalSite = setIsoData(this.context);
@@ -19,8 +19,8 @@ export class ErrorPage extends Component<any, any> {
       <div className="error-page container-lg text-center">
         <h1>
           {errorPageData
-            ? i18n.t("error_page_title")
-            : i18n.t("not_found_page_title")}
+            ? I18NextService.i18n.t("error_page_title")
+            : I18NextService.i18n.t("not_found_page_title")}
         </h1>
         {errorPageData ? (
           <T i18nKey="error_page_paragraph" className="p-4" parent="p">
@@ -28,18 +28,18 @@ export class ErrorPage extends Component<any, any> {
             <a href="https://matrix.to/#/#lemmy-space:matrix.org">#</a>#
           </T>
         ) : (
-          <p>{i18n.t("not_found_page_message")}</p>
+          <p>{I18NextService.i18n.t("not_found_page_message")}</p>
         )}
         {!errorPageData && (
           <Link to="/" replace>
-            {i18n.t("not_found_return_home_button")}
+            {I18NextService.i18n.t("not_found_return_home_button")}
           </Link>
         )}
         {errorPageData?.adminMatrixIds &&
           errorPageData.adminMatrixIds.length > 0 && (
             <>
               <div>
-                {i18n.t("error_page_admin_matrix", {
+                {I18NextService.i18n.t("error_page_admin_matrix", {
                   instance:
                     this.isoData.site_res?.site_view.site.name ??
                     "this instance",
index 601045a408708d2c7ff296e99aa6848ccbfae896..6409ef3563a939dde0ff7c9b0e425da3cd0bc254 100644 (file)
@@ -2,7 +2,7 @@ import { Component } from "inferno";
 import { NavLink } from "inferno-router";
 import { GetSiteResponse } from "lemmy-js-client";
 import { docsUrl, joinLemmyUrl, repoUrl } from "../../config";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 import { VERSION } from "../../version";
 
 interface FooterProps {
@@ -29,36 +29,36 @@ export class Footer extends Component<FooterProps, any> {
             </li>
             <li className="nav-item">
               <NavLink className="nav-link" to="/modlog">
-                {i18n.t("modlog")}
+                {I18NextService.i18n.t("modlog")}
               </NavLink>
             </li>
             {this.props.site?.site_view.local_site.legal_information && (
               <li className="nav-item">
                 <NavLink className="nav-link" to="/legal">
-                  {i18n.t("legal_information")}
+                  {I18NextService.i18n.t("legal_information")}
                 </NavLink>
               </li>
             )}
             {this.props.site?.site_view.local_site.federation_enabled && (
               <li className="nav-item">
                 <NavLink className="nav-link" to="/instances">
-                  {i18n.t("instances")}
+                  {I18NextService.i18n.t("instances")}
                 </NavLink>
               </li>
             )}
             <li className="nav-item">
               <a className="nav-link" href={docsUrl}>
-                {i18n.t("docs")}
+                {I18NextService.i18n.t("docs")}
               </a>
             </li>
             <li className="nav-item">
               <a className="nav-link" href={repoUrl}>
-                {i18n.t("code")}
+                {I18NextService.i18n.t("code")}
               </a>
             </li>
             <li className="nav-item">
               <a className="nav-link" href={joinLemmyUrl}>
-                {i18n.t("join_lemmy")}
+                {I18NextService.i18n.t("join_lemmy")}
               </a>
             </li>
           </ul>
index 12ca05db9cb504a49cc236ecbbd5c0c38c96a7b1..2ede00e183be2d0234adc3c56c205324f1fac140 100644 (file)
@@ -11,8 +11,7 @@ import {
   GetUnreadRegistrationApplicationCountResponse,
 } from "lemmy-js-client";
 import { donateLemmyUrl, updateUnreadCountsInterval } from "../../config";
-import { i18n } from "../../i18next";
-import { UserService } from "../../services";
+import { I18NextService, UserService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
 import { toast } from "../../toast";
 import { Icon } from "../common/icon";
@@ -102,7 +101,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
               <NavLink
                 to="/inbox"
                 className="p-1 nav-link border-0 nav-messages"
-                title={i18n.t("unread_messages", {
+                title={I18NextService.i18n.t("unread_messages", {
                   count: Number(this.state.unreadApplicationCountRes.state),
                   formattedCount: numToSI(this.unreadInboxCount),
                 })}
@@ -121,7 +120,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
                 <NavLink
                   to="/reports"
                   className="p-1 nav-link border-0"
-                  title={i18n.t("unread_reports", {
+                  title={I18NextService.i18n.t("unread_reports", {
                     count: Number(this.unreadReportCount),
                     formattedCount: numToSI(this.unreadReportCount),
                   })}
@@ -141,10 +140,13 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
                 <NavLink
                   to="/registration_applications"
                   className="p-1 nav-link border-0"
-                  title={i18n.t("unread_registration_applications", {
-                    count: Number(this.unreadApplicationCount),
-                    formattedCount: numToSI(this.unreadApplicationCount),
-                  })}
+                  title={I18NextService.i18n.t(
+                    "unread_registration_applications",
+                    {
+                      count: Number(this.unreadApplicationCount),
+                      formattedCount: numToSI(this.unreadApplicationCount),
+                    }
+                  )}
                   onMouseUp={linkEvent(this, handleCollapseClick)}
                 >
                   <Icon icon="clipboard" />
@@ -162,7 +164,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
           className="navbar-toggler border-0 p-1"
           type="button"
           aria-label="menu"
-          data-tippy-content={i18n.t("expand_here")}
+          data-tippy-content={I18NextService.i18n.t("expand_here")}
           data-bs-toggle="collapse"
           data-bs-target="#navbarDropdown"
           aria-controls="navbarDropdown"
@@ -181,10 +183,10 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
               <NavLink
                 to="/communities"
                 className="nav-link"
-                title={i18n.t("communities")}
+                title={I18NextService.i18n.t("communities")}
                 onMouseUp={linkEvent(this, handleCollapseClick)}
               >
-                {i18n.t("communities")}
+                {I18NextService.i18n.t("communities")}
               </NavLink>
             </li>
             <li className="nav-item">
@@ -198,10 +200,10 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
                   state: { prevPath: this.currentLocation },
                 }}
                 className="nav-link"
-                title={i18n.t("create_post")}
+                title={I18NextService.i18n.t("create_post")}
                 onMouseUp={linkEvent(this, handleCollapseClick)}
               >
-                {i18n.t("create_post")}
+                {I18NextService.i18n.t("create_post")}
               </NavLink>
             </li>
             {this.props.siteRes && canCreateCommunity(this.props.siteRes) && (
@@ -209,22 +211,22 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
                 <NavLink
                   to="/create_community"
                   className="nav-link"
-                  title={i18n.t("create_community")}
+                  title={I18NextService.i18n.t("create_community")}
                   onMouseUp={linkEvent(this, handleCollapseClick)}
                 >
-                  {i18n.t("create_community")}
+                  {I18NextService.i18n.t("create_community")}
                 </NavLink>
               </li>
             )}
             <li className="nav-item">
               <a
                 className="nav-link d-inline-flex align-items-center d-md-inline-block"
-                title={i18n.t("support_lemmy")}
+                title={I18NextService.i18n.t("support_lemmy")}
                 href={donateLemmyUrl}
               >
                 <Icon icon="heart" classes="small" />
                 <span className="d-inline ms-1 d-md-none ms-md-0">
-                  {i18n.t("support_lemmy")}
+                  {I18NextService.i18n.t("support_lemmy")}
                 </span>
               </a>
             </li>
@@ -234,12 +236,12 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
               <NavLink
                 to="/search"
                 className="nav-link d-inline-flex align-items-center d-md-inline-block"
-                title={i18n.t("search")}
+                title={I18NextService.i18n.t("search")}
                 onMouseUp={linkEvent(this, handleCollapseClick)}
               >
                 <Icon icon="search" />
                 <span className="d-inline ms-1 d-md-none ms-md-0">
-                  {i18n.t("search")}
+                  {I18NextService.i18n.t("search")}
                 </span>
               </NavLink>
             </li>
@@ -248,12 +250,12 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
                 <NavLink
                   to="/admin"
                   className="nav-link d-inline-flex align-items-center d-md-inline-block"
-                  title={i18n.t("admin_settings")}
+                  title={I18NextService.i18n.t("admin_settings")}
                   onMouseUp={linkEvent(this, handleCollapseClick)}
                 >
                   <Icon icon="settings" />
                   <span className="d-inline ms-1 d-md-none ms-md-0">
-                    {i18n.t("admin_settings")}
+                    {I18NextService.i18n.t("admin_settings")}
                   </span>
                 </NavLink>
               </li>
@@ -264,7 +266,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
                   <NavLink
                     className="nav-link d-inline-flex align-items-center d-md-inline-block"
                     to="/inbox"
-                    title={i18n.t("unread_messages", {
+                    title={I18NextService.i18n.t("unread_messages", {
                       count: Number(this.unreadInboxCount),
                       formattedCount: numToSI(this.unreadInboxCount),
                     })}
@@ -272,7 +274,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
                   >
                     <Icon icon="bell" />
                     <span className="badge text-bg-light d-inline ms-1 d-md-none ms-md-0">
-                      {i18n.t("unread_messages", {
+                      {I18NextService.i18n.t("unread_messages", {
                         count: Number(this.unreadInboxCount),
                         formattedCount: numToSI(this.unreadInboxCount),
                       })}
@@ -289,7 +291,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
                     <NavLink
                       className="nav-link d-inline-flex align-items-center d-md-inline-block"
                       to="/reports"
-                      title={i18n.t("unread_reports", {
+                      title={I18NextService.i18n.t("unread_reports", {
                         count: Number(this.unreadReportCount),
                         formattedCount: numToSI(this.unreadReportCount),
                       })}
@@ -297,7 +299,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
                     >
                       <Icon icon="shield" />
                       <span className="badge text-bg-light d-inline ms-1 d-md-none ms-md-0">
-                        {i18n.t("unread_reports", {
+                        {I18NextService.i18n.t("unread_reports", {
                           count: Number(this.unreadReportCount),
                           formattedCount: numToSI(this.unreadReportCount),
                         })}
@@ -315,18 +317,26 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
                     <NavLink
                       to="/registration_applications"
                       className="nav-link d-inline-flex align-items-center d-md-inline-block"
-                      title={i18n.t("unread_registration_applications", {
-                        count: Number(this.unreadApplicationCount),
-                        formattedCount: numToSI(this.unreadApplicationCount),
-                      })}
+                      title={I18NextService.i18n.t(
+                        "unread_registration_applications",
+                        {
+                          count: Number(this.unreadApplicationCount),
+                          formattedCount: numToSI(this.unreadApplicationCount),
+                        }
+                      )}
                       onMouseUp={linkEvent(this, handleCollapseClick)}
                     >
                       <Icon icon="clipboard" />
                       <span className="badge text-bg-light d-inline ms-1 d-md-none ms-md-0">
-                        {i18n.t("unread_registration_applications", {
-                          count: Number(this.unreadApplicationCount),
-                          formattedCount: numToSI(this.unreadApplicationCount),
-                        })}
+                        {I18NextService.i18n.t(
+                          "unread_registration_applications",
+                          {
+                            count: Number(this.unreadApplicationCount),
+                            formattedCount: numToSI(
+                              this.unreadApplicationCount
+                            ),
+                          }
+                        )}
                       </span>
                       {this.unreadApplicationCount > 0 && (
                         <span className="mx-1 badge text-bg-light">
@@ -357,22 +367,22 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
                         <NavLink
                           to={`/u/${person.name}`}
                           className="dropdown-item px-2"
-                          title={i18n.t("profile")}
+                          title={I18NextService.i18n.t("profile")}
                           onMouseUp={linkEvent(this, handleCollapseClick)}
                         >
                           <Icon icon="user" classes="me-1" />
-                          {i18n.t("profile")}
+                          {I18NextService.i18n.t("profile")}
                         </NavLink>
                       </li>
                       <li>
                         <NavLink
                           to="/settings"
                           className="dropdown-item px-2"
-                          title={i18n.t("settings")}
+                          title={I18NextService.i18n.t("settings")}
                           onMouseUp={linkEvent(this, handleCollapseClick)}
                         >
                           <Icon icon="settings" classes="me-1" />
-                          {i18n.t("settings")}
+                          {I18NextService.i18n.t("settings")}
                         </NavLink>
                       </li>
                       <li>
@@ -384,7 +394,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
                           onClick={linkEvent(this, handleLogOut)}
                         >
                           <Icon icon="log-out" classes="me-1" />
-                          {i18n.t("logout")}
+                          {I18NextService.i18n.t("logout")}
                         </button>
                       </li>
                     </ul>
@@ -397,20 +407,20 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
                   <NavLink
                     to="/login"
                     className="nav-link"
-                    title={i18n.t("login")}
+                    title={I18NextService.i18n.t("login")}
                     onMouseUp={linkEvent(this, handleCollapseClick)}
                   >
-                    {i18n.t("login")}
+                    {I18NextService.i18n.t("login")}
                   </NavLink>
                 </li>
                 <li className="nav-item">
                   <NavLink
                     to="/signup"
                     className="nav-link"
-                    title={i18n.t("sign_up")}
+                    title={I18NextService.i18n.t("sign_up")}
                     onMouseUp={linkEvent(this, handleCollapseClick)}
                   >
-                    {i18n.t("sign_up")}
+                    {I18NextService.i18n.t("sign_up")}
                   </NavLink>
                 </li>
               </>
@@ -504,7 +514,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
     if (UserService.Instance.myUserInfo) {
       document.addEventListener("DOMContentLoaded", function () {
         if (!Notification) {
-          toast(i18n.t("notifications_error"), "danger");
+          toast(I18NextService.i18n.t("notifications_error"), "danger");
           return;
         }
 
index c399fb06a666ef42537b1b69618539441349ec83..294960a812d35711983c4e33728189ae74fb7e36 100644 (file)
@@ -4,9 +4,8 @@ import { Component } from "inferno";
 import { T } from "inferno-i18next-dess";
 import { Link } from "inferno-router";
 import { CreateComment, EditComment, Language } from "lemmy-js-client";
-import { i18n } from "../../i18next";
 import { CommentNodeI } from "../../interfaces";
-import { UserService } from "../../services";
+import { I18NextService, UserService } from "../../services";
 import { Icon } from "../common/icon";
 import { MarkdownTextArea } from "../common/markdown-textarea";
 
@@ -58,7 +57,7 @@ export class CommentForm extends Component<CommentFormProps, any> {
             disabled={this.props.disabled}
             onSubmit={this.handleCommentSubmit}
             onReplyCancel={this.props.onReplyCancel}
-            placeholder={i18n.t("comment_here")}
+            placeholder={I18NextService.i18n.t("comment_here") ?? undefined}
             allLanguages={this.props.allLanguages}
             siteLanguages={this.props.siteLanguages}
           />
@@ -79,10 +78,10 @@ export class CommentForm extends Component<CommentFormProps, any> {
 
   get buttonTitle(): string {
     return typeof this.props.node === "number"
-      ? capitalizeFirstLetter(i18n.t("post"))
+      ? capitalizeFirstLetter(I18NextService.i18n.t("post"))
       : this.props.edit
-      ? capitalizeFirstLetter(i18n.t("save"))
-      : capitalizeFirstLetter(i18n.t("reply"));
+      ? capitalizeFirstLetter(I18NextService.i18n.t("save"))
+      : capitalizeFirstLetter(I18NextService.i18n.t("reply"));
   }
 
   handleCommentSubmit(content: string, form_id: string, language_id?: number) {
index f6cb4b221f77f16b0eb4a65d655883f88befd923..b558d142ce9f10646f8cfe30ebe84f68a90e1609 100644 (file)
@@ -48,7 +48,6 @@ import {
 } from "lemmy-js-client";
 import moment from "moment";
 import { commentTreeMaxDepth } from "../../config";
-import { i18n } from "../../i18next";
 import {
   BanType,
   CommentNodeI,
@@ -57,7 +56,7 @@ import {
   VoteType,
 } from "../../interfaces";
 import { mdToHtml, mdToHtmlNoImages } from "../../markdown";
-import { UserService } from "../../services";
+import { I18NextService, UserService } from "../../services";
 import { setupTippy } from "../../tippy";
 import { Icon, PurgeWarning, Spinner } from "../common/icon";
 import { MomentTime } from "../common/moment-time";
@@ -241,8 +240,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
 
     const purgeTypeText =
       this.state.purgeType == PurgeType.Comment
-        ? i18n.t("purge_comment")
-        : `${i18n.t("purge")} ${cv.creator.name}`;
+        ? I18NextService.i18n.t("purge_comment")
+        : `${I18NextService.i18n.t("purge")} ${cv.creator.name}`;
 
     const canMod_ = canMod(
       cv.creator.id,
@@ -314,27 +313,27 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
               )}
               {this.isPostCreator && (
                 <div className="badge text-bg-light d-none d-sm-inline me-2">
-                  {i18n.t("creator")}
+                  {I18NextService.i18n.t("creator")}
                 </div>
               )}
               {isMod_ && (
                 <div className="badge text-bg-light d-none d-sm-inline me-2">
-                  {i18n.t("mod")}
+                  {I18NextService.i18n.t("mod")}
                 </div>
               )}
               {isAdmin_ && (
                 <div className="badge text-bg-light d-none d-sm-inline me-2">
-                  {i18n.t("admin")}
+                  {I18NextService.i18n.t("admin")}
                 </div>
               )}
               {cv.creator.bot_account && (
                 <div className="badge text-bg-light d-none d-sm-inline me-2">
-                  {i18n.t("bot_account").toLowerCase()}
+                  {I18NextService.i18n.t("bot_account").toLowerCase()}
                 </div>
               )}
               {this.props.showCommunity && (
                 <>
-                  <span className="mx-1">{i18n.t("to")}</span>
+                  <span className="mx-1">{I18NextService.i18n.t("to")}</span>
                   <CommunityLink community={cv.community} />
                   <span className="mx-2">•</span>
                   <Link className="me-2" to={`/post/${cv.post.id}`}>
@@ -366,7 +365,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                     ) : (
                       <span
                         className="me-1 font-weight-bold"
-                        aria-label={i18n.t("number_of_points", {
+                        aria-label={I18NextService.i18n.t("number_of_points", {
                           count: Number(this.commentView.counts.score),
                           formattedCount: numToSI(
                             this.commentView.counts.score
@@ -426,13 +425,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                       onClick={linkEvent(this, this.handleMarkAsRead)}
                       data-tippy-content={
                         this.commentReplyOrMentionRead
-                          ? i18n.t("mark_as_unread")
-                          : i18n.t("mark_as_read")
+                          ? I18NextService.i18n.t("mark_as_unread")
+                          : I18NextService.i18n.t("mark_as_read")
                       }
                       aria-label={
                         this.commentReplyOrMentionRead
-                          ? i18n.t("mark_as_unread")
-                          : i18n.t("mark_as_read")
+                          ? I18NextService.i18n.t("mark_as_unread")
+                          : I18NextService.i18n.t("mark_as_read")
                       }
                     >
                       {this.state.readLoading ? (
@@ -456,8 +455,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                             : "text-muted"
                         }`}
                         onClick={linkEvent(this, this.handleUpvote)}
-                        data-tippy-content={i18n.t("upvote")}
-                        aria-label={i18n.t("upvote")}
+                        data-tippy-content={I18NextService.i18n.t("upvote")}
+                        aria-label={I18NextService.i18n.t("upvote")}
                         aria-pressed={this.commentView.my_vote === 1}
                       >
                         {this.state.upvoteLoading ? (
@@ -483,8 +482,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                               : "text-muted"
                           }`}
                           onClick={linkEvent(this, this.handleDownvote)}
-                          data-tippy-content={i18n.t("downvote")}
-                          aria-label={i18n.t("downvote")}
+                          data-tippy-content={I18NextService.i18n.t("downvote")}
+                          aria-label={I18NextService.i18n.t("downvote")}
                           aria-pressed={this.commentView.my_vote === -1}
                         >
                           {this.state.downvoteLoading ? (
@@ -506,8 +505,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                       <button
                         className="btn btn-link btn-animate text-muted"
                         onClick={linkEvent(this, this.handleReplyClick)}
-                        data-tippy-content={i18n.t("reply")}
-                        aria-label={i18n.t("reply")}
+                        data-tippy-content={I18NextService.i18n.t("reply")}
+                        aria-label={I18NextService.i18n.t("reply")}
                       >
                         <Icon icon="reply1" classes="icon-inline" />
                       </button>
@@ -515,8 +514,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                         <button
                           className="btn btn-link btn-animate text-muted btn-more"
                           onClick={linkEvent(this, this.handleShowAdvanced)}
-                          data-tippy-content={i18n.t("more")}
-                          aria-label={i18n.t("more")}
+                          data-tippy-content={I18NextService.i18n.t("more")}
+                          aria-label={I18NextService.i18n.t("more")}
                         >
                           <Icon icon="more-vertical" classes="icon-inline" />
                         </button>
@@ -527,7 +526,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                               <Link
                                 className="btn btn-link btn-animate text-muted"
                                 to={`/create_private_message/${cv.creator.id}`}
-                                title={i18n.t("message").toLowerCase()}
+                                title={I18NextService.i18n
+                                  .t("message")
+                                  .toLowerCase()}
                               >
                                 <Icon icon="mail" />
                               </Link>
@@ -537,10 +538,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                   this,
                                   this.handleShowReportDialog
                                 )}
-                                data-tippy-content={i18n.t(
+                                data-tippy-content={I18NextService.i18n.t(
+                                  "show_report_dialog"
+                                )}
+                                aria-label={I18NextService.i18n.t(
                                   "show_report_dialog"
                                 )}
-                                aria-label={i18n.t("show_report_dialog")}
                               >
                                 <Icon icon="flag" />
                               </button>
@@ -550,8 +553,10 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                   this,
                                   this.handleBlockPerson
                                 )}
-                                data-tippy-content={i18n.t("block_user")}
-                                aria-label={i18n.t("block_user")}
+                                data-tippy-content={I18NextService.i18n.t(
+                                  "block_user"
+                                )}
+                                aria-label={I18NextService.i18n.t("block_user")}
                               >
                                 {this.state.blockPersonLoading ? (
                                   <Spinner />
@@ -565,10 +570,14 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                             className="btn btn-link btn-animate text-muted"
                             onClick={linkEvent(this, this.handleSaveComment)}
                             data-tippy-content={
-                              cv.saved ? i18n.t("unsave") : i18n.t("save")
+                              cv.saved
+                                ? I18NextService.i18n.t("unsave")
+                                : I18NextService.i18n.t("save")
                             }
                             aria-label={
-                              cv.saved ? i18n.t("unsave") : i18n.t("save")
+                              cv.saved
+                                ? I18NextService.i18n.t("unsave")
+                                : I18NextService.i18n.t("save")
                             }
                           >
                             {this.state.saveLoading ? (
@@ -585,8 +594,10 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                           <button
                             className="btn btn-link btn-animate text-muted"
                             onClick={linkEvent(this, this.handleViewSource)}
-                            data-tippy-content={i18n.t("view_source")}
-                            aria-label={i18n.t("view_source")}
+                            data-tippy-content={I18NextService.i18n.t(
+                              "view_source"
+                            )}
+                            aria-label={I18NextService.i18n.t("view_source")}
                           >
                             <Icon
                               icon="file-text"
@@ -600,8 +611,10 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                               <button
                                 className="btn btn-link btn-animate text-muted"
                                 onClick={linkEvent(this, this.handleEditClick)}
-                                data-tippy-content={i18n.t("edit")}
-                                aria-label={i18n.t("edit")}
+                                data-tippy-content={I18NextService.i18n.t(
+                                  "edit"
+                                )}
+                                aria-label={I18NextService.i18n.t("edit")}
                               >
                                 <Icon icon="edit" classes="icon-inline" />
                               </button>
@@ -613,13 +626,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                 )}
                                 data-tippy-content={
                                   !cv.comment.deleted
-                                    ? i18n.t("delete")
-                                    : i18n.t("restore")
+                                    ? I18NextService.i18n.t("delete")
+                                    : I18NextService.i18n.t("restore")
                                 }
                                 aria-label={
                                   !cv.comment.deleted
-                                    ? i18n.t("delete")
-                                    : i18n.t("restore")
+                                    ? I18NextService.i18n.t("delete")
+                                    : I18NextService.i18n.t("restore")
                                 }
                               >
                                 {this.state.deleteLoading ? (
@@ -643,13 +656,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                   )}
                                   data-tippy-content={
                                     !cv.comment.distinguished
-                                      ? i18n.t("distinguish")
-                                      : i18n.t("undistinguish")
+                                      ? I18NextService.i18n.t("distinguish")
+                                      : I18NextService.i18n.t("undistinguish")
                                   }
                                   aria-label={
                                     !cv.comment.distinguished
-                                      ? i18n.t("distinguish")
-                                      : i18n.t("undistinguish")
+                                      ? I18NextService.i18n.t("distinguish")
+                                      : I18NextService.i18n.t("undistinguish")
                                   }
                                 >
                                   <Icon
@@ -672,9 +685,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                     this,
                                     this.handleModRemoveShow
                                   )}
-                                  aria-label={i18n.t("remove")}
+                                  aria-label={I18NextService.i18n.t("remove")}
                                 >
-                                  {i18n.t("remove")}
+                                  {I18NextService.i18n.t("remove")}
                                 </button>
                               ) : (
                                 <button
@@ -683,12 +696,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                     this,
                                     this.handleRemoveComment
                                   )}
-                                  aria-label={i18n.t("restore")}
+                                  aria-label={I18NextService.i18n.t("restore")}
                                 >
                                   {this.state.removeLoading ? (
                                     <Spinner />
                                   ) : (
-                                    i18n.t("restore")
+                                    I18NextService.i18n.t("restore")
                                   )}
                                 </button>
                               )}
@@ -705,9 +718,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                       this,
                                       this.handleModBanFromCommunityShow
                                     )}
-                                    aria-label={i18n.t("ban_from_community")}
+                                    aria-label={I18NextService.i18n.t(
+                                      "ban_from_community"
+                                    )}
                                   >
-                                    {i18n.t("ban_from_community")}
+                                    {I18NextService.i18n.t(
+                                      "ban_from_community"
+                                    )}
                                   </button>
                                 ) : (
                                   <button
@@ -716,12 +733,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                       this,
                                       this.handleBanPersonFromCommunity
                                     )}
-                                    aria-label={i18n.t("unban")}
+                                    aria-label={I18NextService.i18n.t("unban")}
                                   >
                                     {this.state.banLoading ? (
                                       <Spinner />
                                     ) : (
-                                      i18n.t("unban")
+                                      I18NextService.i18n.t("unban")
                                     )}
                                   </button>
                                 ))}
@@ -735,21 +752,25 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                     )}
                                     aria-label={
                                       isMod_
-                                        ? i18n.t("remove_as_mod")
-                                        : i18n.t("appoint_as_mod")
+                                        ? I18NextService.i18n.t("remove_as_mod")
+                                        : I18NextService.i18n.t(
+                                            "appoint_as_mod"
+                                          )
                                     }
                                   >
                                     {isMod_
-                                      ? i18n.t("remove_as_mod")
-                                      : i18n.t("appoint_as_mod")}
+                                      ? I18NextService.i18n.t("remove_as_mod")
+                                      : I18NextService.i18n.t("appoint_as_mod")}
                                   </button>
                                 ) : (
                                   <>
                                     <button
                                       className="btn btn-link btn-animate text-muted"
-                                      aria-label={i18n.t("are_you_sure")}
+                                      aria-label={I18NextService.i18n.t(
+                                        "are_you_sure"
+                                      )}
                                     >
-                                      {i18n.t("are_you_sure")}
+                                      {I18NextService.i18n.t("are_you_sure")}
                                     </button>
                                     <button
                                       className="btn btn-link btn-animate text-muted"
@@ -757,12 +778,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                         this,
                                         this.handleAddModToCommunity
                                       )}
-                                      aria-label={i18n.t("yes")}
+                                      aria-label={I18NextService.i18n.t("yes")}
                                     >
                                       {this.state.addModLoading ? (
                                         <Spinner />
                                       ) : (
-                                        i18n.t("yes")
+                                        I18NextService.i18n.t("yes")
                                       )}
                                     </button>
                                     <button
@@ -771,9 +792,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                         this,
                                         this.handleCancelConfirmAppointAsMod
                                       )}
-                                      aria-label={i18n.t("no")}
+                                      aria-label={I18NextService.i18n.t("no")}
                                     >
-                                      {i18n.t("no")}
+                                      {I18NextService.i18n.t("no")}
                                     </button>
                                   </>
                                 ))}
@@ -790,17 +811,21 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                   this,
                                   this.handleShowConfirmTransferCommunity
                                 )}
-                                aria-label={i18n.t("transfer_community")}
+                                aria-label={I18NextService.i18n.t(
+                                  "transfer_community"
+                                )}
                               >
-                                {i18n.t("transfer_community")}
+                                {I18NextService.i18n.t("transfer_community")}
                               </button>
                             ) : (
                               <>
                                 <button
                                   className="btn btn-link btn-animate text-muted"
-                                  aria-label={i18n.t("are_you_sure")}
+                                  aria-label={I18NextService.i18n.t(
+                                    "are_you_sure"
+                                  )}
                                 >
-                                  {i18n.t("are_you_sure")}
+                                  {I18NextService.i18n.t("are_you_sure")}
                                 </button>
                                 <button
                                   className="btn btn-link btn-animate text-muted"
@@ -808,12 +833,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                     this,
                                     this.handleTransferCommunity
                                   )}
-                                  aria-label={i18n.t("yes")}
+                                  aria-label={I18NextService.i18n.t("yes")}
                                 >
                                   {this.state.transferCommunityLoading ? (
                                     <Spinner />
                                   ) : (
-                                    i18n.t("yes")
+                                    I18NextService.i18n.t("yes")
                                   )}
                                 </button>
                                 <button
@@ -823,9 +848,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                     this
                                       .handleCancelShowConfirmTransferCommunity
                                   )}
-                                  aria-label={i18n.t("no")}
+                                  aria-label={I18NextService.i18n.t("no")}
                                 >
-                                  {i18n.t("no")}
+                                  {I18NextService.i18n.t("no")}
                                 </button>
                               </>
                             ))}
@@ -840,9 +865,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                       this,
                                       this.handlePurgePersonShow
                                     )}
-                                    aria-label={i18n.t("purge_user")}
+                                    aria-label={I18NextService.i18n.t(
+                                      "purge_user"
+                                    )}
                                   >
-                                    {i18n.t("purge_user")}
+                                    {I18NextService.i18n.t("purge_user")}
                                   </button>
                                   <button
                                     className="btn btn-link btn-animate text-muted"
@@ -850,9 +877,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                       this,
                                       this.handlePurgeCommentShow
                                     )}
-                                    aria-label={i18n.t("purge_comment")}
+                                    aria-label={I18NextService.i18n.t(
+                                      "purge_comment"
+                                    )}
                                   >
-                                    {i18n.t("purge_comment")}
+                                    {I18NextService.i18n.t("purge_comment")}
                                   </button>
 
                                   {!isBanned(cv.creator) ? (
@@ -862,9 +891,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                         this,
                                         this.handleModBanShow
                                       )}
-                                      aria-label={i18n.t("ban_from_site")}
+                                      aria-label={I18NextService.i18n.t(
+                                        "ban_from_site"
+                                      )}
                                     >
-                                      {i18n.t("ban_from_site")}
+                                      {I18NextService.i18n.t("ban_from_site")}
                                     </button>
                                   ) : (
                                     <button
@@ -873,12 +904,14 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                         this,
                                         this.handleBanPerson
                                       )}
-                                      aria-label={i18n.t("unban_from_site")}
+                                      aria-label={I18NextService.i18n.t(
+                                        "unban_from_site"
+                                      )}
                                     >
                                       {this.state.banLoading ? (
                                         <Spinner />
                                       ) : (
-                                        i18n.t("unban_from_site")
+                                        I18NextService.i18n.t("unban_from_site")
                                       )}
                                     </button>
                                   )}
@@ -895,18 +928,24 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                     )}
                                     aria-label={
                                       isAdmin_
-                                        ? i18n.t("remove_as_admin")
-                                        : i18n.t("appoint_as_admin")
+                                        ? I18NextService.i18n.t(
+                                            "remove_as_admin"
+                                          )
+                                        : I18NextService.i18n.t(
+                                            "appoint_as_admin"
+                                          )
                                     }
                                   >
                                     {isAdmin_
-                                      ? i18n.t("remove_as_admin")
-                                      : i18n.t("appoint_as_admin")}
+                                      ? I18NextService.i18n.t("remove_as_admin")
+                                      : I18NextService.i18n.t(
+                                          "appoint_as_admin"
+                                        )}
                                   </button>
                                 ) : (
                                   <>
                                     <button className="btn btn-link btn-animate text-muted">
-                                      {i18n.t("are_you_sure")}
+                                      {I18NextService.i18n.t("are_you_sure")}
                                     </button>
                                     <button
                                       className="btn btn-link btn-animate text-muted"
@@ -914,12 +953,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                         this,
                                         this.handleAddAdmin
                                       )}
-                                      aria-label={i18n.t("yes")}
+                                      aria-label={I18NextService.i18n.t("yes")}
                                     >
                                       {this.state.addAdminLoading ? (
                                         <Spinner />
                                       ) : (
-                                        i18n.t("yes")
+                                        I18NextService.i18n.t("yes")
                                       )}
                                     </button>
                                     <button
@@ -928,9 +967,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                                         this,
                                         this.handleCancelConfirmAppointAsAdmin
                                       )}
-                                      aria-label={i18n.t("no")}
+                                      aria-label={I18NextService.i18n.t("no")}
                                     >
-                                      {i18n.t("no")}
+                                      {I18NextService.i18n.t("no")}
                                     </button>
                                   </>
                                 ))}
@@ -961,7 +1000,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                 <Spinner />
               ) : (
                 <>
-                  {i18n.t("x_more_replies", {
+                  {I18NextService.i18n.t("x_more_replies", {
                     count: node.comment_view.counts.child_count,
                     formattedCount: numToSI(
                       node.comment_view.counts.child_count
@@ -983,22 +1022,22 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
               className="visually-hidden"
               htmlFor={`mod-remove-reason-${cv.comment.id}`}
             >
-              {i18n.t("reason")}
+              {I18NextService.i18n.t("reason")}
             </label>
             <input
               type="text"
               id={`mod-remove-reason-${cv.comment.id}`}
               className="form-control me-2"
-              placeholder={i18n.t("reason")}
+              placeholder={I18NextService.i18n.t("reason")}
               value={this.state.removeReason}
               onInput={linkEvent(this, this.handleModRemoveReasonChange)}
             />
             <button
               type="submit"
               className="btn btn-secondary"
-              aria-label={i18n.t("remove_comment")}
+              aria-label={I18NextService.i18n.t("remove_comment")}
             >
-              {i18n.t("remove_comment")}
+              {I18NextService.i18n.t("remove_comment")}
             </button>
           </form>
         )}
@@ -1011,23 +1050,23 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
               className="visually-hidden"
               htmlFor={`report-reason-${cv.comment.id}`}
             >
-              {i18n.t("reason")}
+              {I18NextService.i18n.t("reason")}
             </label>
             <input
               type="text"
               required
               id={`report-reason-${cv.comment.id}`}
               className="form-control me-2"
-              placeholder={i18n.t("reason")}
+              placeholder={I18NextService.i18n.t("reason")}
               value={this.state.reportReason}
               onInput={linkEvent(this, this.handleReportReasonChange)}
             />
             <button
               type="submit"
               className="btn btn-secondary"
-              aria-label={i18n.t("create_report")}
+              aria-label={I18NextService.i18n.t("create_report")}
             >
-              {i18n.t("create_report")}
+              {I18NextService.i18n.t("create_report")}
             </button>
           </form>
         )}
@@ -1038,13 +1077,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                 className="col-form-label"
                 htmlFor={`mod-ban-reason-${cv.comment.id}`}
               >
-                {i18n.t("reason")}
+                {I18NextService.i18n.t("reason")}
               </label>
               <input
                 type="text"
                 id={`mod-ban-reason-${cv.comment.id}`}
                 className="form-control me-2"
-                placeholder={i18n.t("reason")}
+                placeholder={I18NextService.i18n.t("reason")}
                 value={this.state.banReason}
                 onInput={linkEvent(this, this.handleModBanReasonChange)}
               />
@@ -1052,13 +1091,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                 className="col-form-label"
                 htmlFor={`mod-ban-expires-${cv.comment.id}`}
               >
-                {i18n.t("expires")}
+                {I18NextService.i18n.t("expires")}
               </label>
               <input
                 type="number"
                 id={`mod-ban-expires-${cv.comment.id}`}
                 className="form-control me-2"
-                placeholder={i18n.t("number_of_days")}
+                placeholder={I18NextService.i18n.t("number_of_days")}
                 value={this.state.banExpireDays}
                 onInput={linkEvent(this, this.handleModBanExpireDaysChange)}
               />
@@ -1074,9 +1113,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
                   <label
                     className="form-check-label"
                     htmlFor="mod-ban-remove-data"
-                    title={i18n.t("remove_content_more")}
+                    title={I18NextService.i18n.t("remove_content_more")}
                   >
-                    {i18n.t("remove_content")}
+                    {I18NextService.i18n.t("remove_content")}
                   </label>
                 </div>
               </div>
@@ -1084,19 +1123,19 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
             {/* TODO hold off on expires until later */}
             {/* <div class="mb-3 row"> */}
             {/*   <label class="col-form-label">Expires</label> */}
-            {/*   <input type="date" class="form-control me-2" placeholder={i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
+            {/*   <input type="date" class="form-control me-2" placeholder={I18NextService.i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
             {/* </div> */}
             <div className="mb-3 row">
               <button
                 type="submit"
                 className="btn btn-secondary"
-                aria-label={i18n.t("ban")}
+                aria-label={I18NextService.i18n.t("ban")}
               >
                 {this.state.banLoading ? (
                   <Spinner />
                 ) : (
                   <span>
-                    {i18n.t("ban")} {cv.creator.name}
+                    {I18NextService.i18n.t("ban")} {cv.creator.name}
                   </span>
                 )}
               </button>
@@ -1108,13 +1147,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
           <form onSubmit={linkEvent(this, this.handlePurgeBothSubmit)}>
             <PurgeWarning />
             <label className="visually-hidden" htmlFor="purge-reason">
-              {i18n.t("reason")}
+              {I18NextService.i18n.t("reason")}
             </label>
             <input
               type="text"
               id="purge-reason"
               className="form-control my-3"
-              placeholder={i18n.t("reason")}
+              placeholder={I18NextService.i18n.t("reason")}
               value={this.state.purgeReason}
               onInput={linkEvent(this, this.handlePurgeReasonChange)}
             />
@@ -1209,8 +1248,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
     });
 
     const title = this.props.showContext
-      ? i18n.t("show_context")
-      : i18n.t("link");
+      ? I18NextService.i18n.t("show_context")
+      : I18NextService.i18n.t("link");
 
     // The context button should show the parent comment by default
     const parentCommentId = getCommentParentId(cv.comment) ?? cv.comment.id;
@@ -1255,17 +1294,17 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
   }
 
   get pointsTippy(): string {
-    const points = i18n.t("number_of_points", {
+    const points = I18NextService.i18n.t("number_of_points", {
       count: Number(this.commentView.counts.score),
       formattedCount: numToSI(this.commentView.counts.score),
     });
 
-    const upvotes = i18n.t("number_of_upvotes", {
+    const upvotes = I18NextService.i18n.t("number_of_upvotes", {
       count: Number(this.commentView.counts.upvotes),
       formattedCount: numToSI(this.commentView.counts.upvotes),
     });
 
-    const downvotes = i18n.t("number_of_downvotes", {
+    const downvotes = I18NextService.i18n.t("number_of_downvotes", {
       count: Number(this.commentView.counts.downvotes),
       formattedCount: numToSI(this.commentView.counts.downvotes),
     });
@@ -1274,15 +1313,17 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
   }
 
   get expandText(): string {
-    return this.state.collapsed ? i18n.t("expand") : i18n.t("collapse");
+    return this.state.collapsed
+      ? I18NextService.i18n.t("expand")
+      : I18NextService.i18n.t("collapse");
   }
 
   get commentUnlessRemoved(): string {
     const comment = this.commentView.comment;
     return comment.removed
-      ? `*${i18n.t("removed")}*`
+      ? `*${I18NextService.i18n.t("removed")}*`
       : comment.deleted
-      ? `*${i18n.t("deleted")}*`
+      ? `*${I18NextService.i18n.t("deleted")}*`
       : comment.content;
   }
 
index b3630096e37cde8a4dac48d8e29e1e765b153ec4..3b328f67a28cf1103e391fe1a4800c96cb95fd82 100644 (file)
@@ -6,8 +6,8 @@ import {
   CommentView,
   ResolveCommentReport,
 } from "lemmy-js-client";
-import { i18n } from "../../i18next";
 import { CommentNodeI, CommentViewType } from "../../interfaces";
+import { I18NextService } from "../../services";
 import { Icon, Spinner } from "../common/icon";
 import { PersonListing } from "../person/person-listing";
 import { CommentNode } from "./comment-node";
@@ -43,7 +43,7 @@ export class CommentReport extends Component<
   render() {
     const r = this.props.report;
     const comment = r.comment;
-    const tippyContent = i18n.t(
+    const tippyContent = I18NextService.i18n.t(
       r.comment_report.resolved ? "unresolve_report" : "resolve_report"
     );
 
@@ -102,10 +102,11 @@ export class CommentReport extends Component<
           onEditComment={() => Promise.resolve({ state: "empty" })}
         />
         <div>
-          {i18n.t("reporter")}: <PersonListing person={r.creator} />
+          {I18NextService.i18n.t("reporter")}:{" "}
+          <PersonListing person={r.creator} />
         </div>
         <div>
-          {i18n.t("reason")}: {r.comment_report.reason}
+          {I18NextService.i18n.t("reason")}: {r.comment_report.reason}
         </div>
         {r.resolver && (
           <div>
index ed9aecf874e9a714b3f7e7176ab2a67d60a0d6bc..c1eeed4677e4261a1ed7646aafa084b0b8a91751 100644 (file)
@@ -5,7 +5,7 @@ import {
   CommunityId,
   SiteAggregates,
 } from "lemmy-js-client";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 
 interface BadgesProps {
   counts: CommunityAggregates | SiteAggregates;
@@ -29,66 +29,82 @@ export const Badges = ({ counts, communityId }: BadgesProps) => {
     <ul className="badges my-1 list-inline">
       <li
         className="list-inline-item badge text-bg-secondary pointer"
-        data-tippy-content={i18n.t("active_users_in_the_last_day", {
-          count: Number(counts.users_active_day),
-          formattedCount: numToSI(counts.users_active_day),
-        })}
+        data-tippy-content={I18NextService.i18n.t(
+          "active_users_in_the_last_day",
+          {
+            count: Number(counts.users_active_day),
+            formattedCount: numToSI(counts.users_active_day),
+          }
+        )}
       >
-        {i18n.t("number_of_users", {
+        {I18NextService.i18n.t("number_of_users", {
           count: Number(counts.users_active_day),
           formattedCount: numToSI(counts.users_active_day),
         })}{" "}
-        / {i18n.t("day")}
+        / {I18NextService.i18n.t("day")}
       </li>
       <li
         className="list-inline-item badge text-bg-secondary pointer"
-        data-tippy-content={i18n.t("active_users_in_the_last_week", {
-          count: Number(counts.users_active_week),
-          formattedCount: numToSI(counts.users_active_week),
-        })}
+        data-tippy-content={I18NextService.i18n.t(
+          "active_users_in_the_last_week",
+          {
+            count: Number(counts.users_active_week),
+            formattedCount: numToSI(counts.users_active_week),
+          }
+        )}
       >
-        {i18n.t("number_of_users", {
+        {I18NextService.i18n.t("number_of_users", {
           count: Number(counts.users_active_week),
           formattedCount: numToSI(counts.users_active_week),
         })}{" "}
-        / {i18n.t("week")}
+        / {I18NextService.i18n.t("week")}
       </li>
       <li
         className="list-inline-item badge text-bg-secondary pointer"
-        data-tippy-content={i18n.t("active_users_in_the_last_month", {
-          count: Number(counts.users_active_month),
-          formattedCount: numToSI(counts.users_active_month),
-        })}
+        data-tippy-content={I18NextService.i18n.t(
+          "active_users_in_the_last_month",
+          {
+            count: Number(counts.users_active_month),
+            formattedCount: numToSI(counts.users_active_month),
+          }
+        )}
       >
-        {i18n.t("number_of_users", {
+        {I18NextService.i18n.t("number_of_users", {
           count: Number(counts.users_active_month),
           formattedCount: numToSI(counts.users_active_month),
         })}{" "}
-        / {i18n.t("month")}
+        / {I18NextService.i18n.t("month")}
       </li>
       <li
         className="list-inline-item badge text-bg-secondary pointer"
-        data-tippy-content={i18n.t("active_users_in_the_last_six_months", {
-          count: Number(counts.users_active_half_year),
-          formattedCount: numToSI(counts.users_active_half_year),
-        })}
+        data-tippy-content={I18NextService.i18n.t(
+          "active_users_in_the_last_six_months",
+          {
+            count: Number(counts.users_active_half_year),
+            formattedCount: numToSI(counts.users_active_half_year),
+          }
+        )}
       >
-        {i18n.t("number_of_users", {
+        {I18NextService.i18n.t("number_of_users", {
           count: Number(counts.users_active_half_year),
           formattedCount: numToSI(counts.users_active_half_year),
         })}{" "}
-        / {i18n.t("number_of_months", { count: 6, formattedCount: 6 })}
+        /{" "}
+        {I18NextService.i18n.t("number_of_months", {
+          count: 6,
+          formattedCount: 6,
+        })}
       </li>
       {isSiteAggregates(counts) && (
         <>
           <li className="list-inline-item badge text-bg-secondary">
-            {i18n.t("number_of_users", {
+            {I18NextService.i18n.t("number_of_users", {
               count: Number(counts.users),
               formattedCount: numToSI(counts.users),
             })}
           </li>
           <li className="list-inline-item badge text-bg-secondary">
-            {i18n.t("number_of_communities", {
+            {I18NextService.i18n.t("number_of_communities", {
               count: Number(counts.communities),
               formattedCount: numToSI(counts.communities),
             })}
@@ -97,20 +113,20 @@ export const Badges = ({ counts, communityId }: BadgesProps) => {
       )}
       {isCommunityAggregates(counts) && (
         <li className="list-inline-item badge text-bg-secondary">
-          {i18n.t("number_of_subscribers", {
+          {I18NextService.i18n.t("number_of_subscribers", {
             count: Number(counts.subscribers),
             formattedCount: numToSI(counts.subscribers),
           })}
         </li>
       )}
       <li className="list-inline-item badge text-bg-secondary">
-        {i18n.t("number_of_posts", {
+        {I18NextService.i18n.t("number_of_posts", {
           count: Number(counts.posts),
           formattedCount: numToSI(counts.posts),
         })}
       </li>
       <li className="list-inline-item badge text-bg-secondary">
-        {i18n.t("number_of_comments", {
+        {I18NextService.i18n.t("number_of_comments", {
           count: Number(counts.comments),
           formattedCount: numToSI(counts.comments),
         })}
@@ -120,7 +136,7 @@ export const Badges = ({ counts, communityId }: BadgesProps) => {
           className="badge text-bg-primary"
           to={`/modlog${communityId ? `/${communityId}` : ""}`}
         >
-          {i18n.t("modlog")}
+          {I18NextService.i18n.t("modlog")}
         </Link>
       </li>
     </ul>
index 18eaed2aa34548a707a28ab93c1ee67b3e7b439a..ad4eebfe8cdebe5d3310838fffbd33702147e878 100644 (file)
@@ -2,7 +2,7 @@ import { randomStr } from "@utils/helpers";
 import { Component, linkEvent } from "inferno";
 import { CommentSortType } from "lemmy-js-client";
 import { relTags, sortingHelpUrl } from "../../config";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 import { Icon } from "./icon";
 
 interface CommentSortSelectProps {
@@ -42,21 +42,21 @@ export class CommentSortSelect extends Component<
           value={this.state.sort}
           onChange={linkEvent(this, this.handleSortChange)}
           className="sort-select form-select d-inline-block w-auto me-2 mb-2"
-          aria-label={i18n.t("sort_type")}
+          aria-label={I18NextService.i18n.t("sort_type")}
         >
           <option disabled aria-hidden="true">
-            {i18n.t("sort_type")}
+            {I18NextService.i18n.t("sort_type")}
           </option>
-          <option value={"Hot"}>{i18n.t("hot")}</option>,
-          <option value={"Top"}>{i18n.t("top")}</option>,
-          <option value={"New"}>{i18n.t("new")}</option>
-          <option value={"Old"}>{i18n.t("old")}</option>
+          <option value={"Hot"}>{I18NextService.i18n.t("hot")}</option>,
+          <option value={"Top"}>{I18NextService.i18n.t("top")}</option>,
+          <option value={"New"}>{I18NextService.i18n.t("new")}</option>
+          <option value={"Old"}>{I18NextService.i18n.t("old")}</option>
         </select>
         <a
           className="sort-select-help text-muted"
           href={sortingHelpUrl}
           rel={relTags}
-          title={i18n.t("sorting_help")}
+          title={I18NextService.i18n.t("sorting_help")}
         >
           <Icon icon="help-circle" classes="icon-inline" />
         </a>
index b61d6840ff7b4e769d806af1a34634337e4138b5..6bf0666cf320db1ac4dcf07be74c4f19172c4077 100644 (file)
@@ -1,6 +1,6 @@
 import { Component, linkEvent } from "inferno";
-import { i18n } from "../../i18next";
 import { DataType } from "../../interfaces";
+import { I18NextService } from "../../services";
 
 interface DataTypeSelectProps {
   type_: DataType;
@@ -44,7 +44,7 @@ export class DataTypeSelect extends Component<
             checked={this.state.type_ == DataType.Post}
             onChange={linkEvent(this, this.handleTypeChange)}
           />
-          {i18n.t("posts")}
+          {I18NextService.i18n.t("posts")}
         </label>
         <label
           className={`pointer btn btn-outline-secondary ${
@@ -58,7 +58,7 @@ export class DataTypeSelect extends Component<
             checked={this.state.type_ == DataType.Comment}
             onChange={linkEvent(this, this.handleTypeChange)}
           />
-          {i18n.t("comments")}
+          {I18NextService.i18n.t("comments")}
         </label>
       </div>
     );
index 6c6037546b4c714269be3e09a5822fbe19c9b417..ba36d755f9c032755e614e492b5418ffd91e1fda 100644 (file)
@@ -1,5 +1,5 @@
 import { Component, linkEvent } from "inferno";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 import { EmojiMart } from "./emoji-mart";
 import { Icon } from "./icon";
 
@@ -28,8 +28,8 @@ export class EmojiPicker extends Component<EmojiPickerProps, EmojiPickerState> {
       <span className="emoji-picker">
         <button
           className="btn btn-sm text-muted"
-          data-tippy-content={i18n.t("emoji")}
-          aria-label={i18n.t("emoji")}
+          data-tippy-content={I18NextService.i18n.t("emoji")}
+          aria-label={I18NextService.i18n.t("emoji")}
           disabled={this.props.disabled}
           onClick={linkEvent(this, this.togglePicker)}
         >
index 63eb461f24e4bb7666dad304ac8983dab913ac20..3a8b270a496d60d85ae325da938c6de263fecdec 100644 (file)
@@ -2,8 +2,8 @@ import { htmlToText } from "html-to-text";
 import { Component } from "inferno";
 import { Helmet } from "inferno-helmet";
 import { httpExternalPath } from "../../env";
-import { i18n } from "../../i18next";
 import { md } from "../../markdown";
+import { I18NextService } from "../../services";
 
 interface HtmlTagsProps {
   title: string;
@@ -21,7 +21,7 @@ export class HtmlTags extends Component<HtmlTagsProps, any> {
 
     return (
       <Helmet title={this.props.title}>
-        <html lang={i18n.resolvedLanguage} />
+        <html lang={I18NextService.i18n.resolvedLanguage} />
 
         {["title", "og:title", "twitter:title"].map(t => (
           <meta key={t} property={t} content={this.props.title} />
index e3f5ba44509808e72c01b8da305edd4234d871c0..7aedee71f30839753e8803ef8f1d55d626d60aec 100644 (file)
@@ -1,6 +1,6 @@
 import classNames from "classnames";
 import { Component } from "inferno";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 
 interface IconProps {
   icon: string;
@@ -61,7 +61,7 @@ export class PurgeWarning extends Component<any, any> {
     return (
       <div className="purge-warning mt-2 alert alert-danger" role="alert">
         <Icon icon="alert-triangle" classes="icon-inline me-2" />
-        {i18n.t("purge_warning")}
+        {I18NextService.i18n.t("purge_warning")}
       </div>
     );
   }
index 44fa5a9efff9c869e9517eef9af389d6c378af8e..5f68ea54ff5d1c2267e1515ff036a3e1f07ac060 100644 (file)
@@ -1,7 +1,6 @@
 import { randomStr } from "@utils/helpers";
 import { Component, linkEvent } from "inferno";
-import { i18n } from "../../i18next";
-import { HttpService, UserService } from "../../services";
+import { HttpService, I18NextService, UserService } from "../../services";
 import { toast } from "../../toast";
 import { Icon } from "./icon";
 
@@ -50,7 +49,7 @@ export class ImageUploadForm extends Component<
               />
               <a
                 onClick={linkEvent(this, this.handleRemoveImage)}
-                aria-label={i18n.t("remove")}
+                aria-label={I18NextService.i18n.t("remove")}
               >
                 <Icon icon="x" classes="mini-overlay" />
               </a>
index 625379e26a4c6155299cb03949acb51b95f40e0d..382eff1e33458bd2cc82de7703628c55f3f9a609 100644 (file)
@@ -3,8 +3,7 @@ import { randomStr } from "@utils/helpers";
 import classNames from "classnames";
 import { Component, linkEvent } from "inferno";
 import { Language } from "lemmy-js-client";
-import { i18n } from "../../i18next";
-import { UserService } from "../../services/UserService";
+import { I18NextService, UserService } from "../../services";
 import { Icon } from "./icon";
 
 interface LanguageSelectProps {
@@ -53,7 +52,7 @@ export class LanguageSelect extends Component<LanguageSelectProps, any> {
       <div className="language-select">
         {this.props.multiple && this.props.showLanguageWarning && (
           <div className="alert alert-warning" role="alert">
-            {i18n.t("undetermined_language_warning")}
+            {I18NextService.i18n.t("undetermined_language_warning")}
           </div>
         )}
         <div className="mb-3 row">
@@ -64,7 +63,9 @@ export class LanguageSelect extends Component<LanguageSelectProps, any> {
             )}
             htmlFor={this.id}
           >
-            {i18n.t(this.props.multiple ? "language_plural" : "language")}
+            {I18NextService.i18n.t(
+              this.props.multiple ? "language_plural" : "language"
+            )}
           </label>
           <div
             className={classNames(`col-sm-${this.props.multiple ? 9 : 10}`, {
@@ -103,13 +104,13 @@ export class LanguageSelect extends Component<LanguageSelectProps, any> {
         })}
         id={this.id}
         onChange={linkEvent(this, this.handleLanguageChange)}
-        aria-label={i18n.t("language_select_placeholder")}
+        aria-label={I18NextService.i18n.t("language_select_placeholder")}
         multiple={this.props.multiple}
         disabled={this.props.disabled}
       >
         {!this.props.multiple && (
           <option selected disabled hidden>
-            {i18n.t("language_select_placeholder")}
+            {I18NextService.i18n.t("language_select_placeholder")}
           </option>
         )}
         {filteredLangs.map(l => (
index d6ed378fe05060189ddef23ff8dccbb0b12c19ab..9d0a1b9f3184a30b5379f846a34af38c0763f333 100644 (file)
@@ -1,8 +1,7 @@
 import { randomStr } from "@utils/helpers";
 import { Component, linkEvent } from "inferno";
 import { ListingType } from "lemmy-js-client";
-import { i18n } from "../../i18next";
-import { UserService } from "../../services";
+import { I18NextService, UserService } from "../../services";
 
 interface ListingTypeSelectProps {
   type_: ListingType;
@@ -42,7 +41,7 @@ export class ListingTypeSelect extends Component<
       <div className="listing-type-select btn-group btn-group-toggle flex-wrap">
         {this.props.showSubscribed && (
           <label
-            title={i18n.t("subscribed_description")}
+            title={I18NextService.i18n.t("subscribed_description")}
             className={`btn btn-outline-secondary 
             ${this.state.type_ == "Subscribed" && "active"}
             ${!UserService.Instance.myUserInfo ? "disabled" : "pointer"}
@@ -57,12 +56,12 @@ export class ListingTypeSelect extends Component<
               onChange={linkEvent(this, this.handleTypeChange)}
               disabled={!UserService.Instance.myUserInfo}
             />
-            {i18n.t("subscribed")}
+            {I18NextService.i18n.t("subscribed")}
           </label>
         )}
         {this.props.showLocal && (
           <label
-            title={i18n.t("local_description")}
+            title={I18NextService.i18n.t("local_description")}
             className={`pointer btn btn-outline-secondary ${
               this.state.type_ == "Local" && "active"
             }`}
@@ -75,11 +74,11 @@ export class ListingTypeSelect extends Component<
               checked={this.state.type_ == "Local"}
               onChange={linkEvent(this, this.handleTypeChange)}
             />
-            {i18n.t("local")}
+            {I18NextService.i18n.t("local")}
           </label>
         )}
         <label
-          title={i18n.t("all_description")}
+          title={I18NextService.i18n.t("all_description")}
           className={`pointer btn btn-outline-secondary ${
             (this.state.type_ == "All" && "active") ||
             (!this.props.showLocal && this.state.type_ == "Local" && "active")
@@ -93,7 +92,7 @@ export class ListingTypeSelect extends Component<
             checked={this.state.type_ == "All"}
             onChange={linkEvent(this, this.handleTypeChange)}
           />
-          {i18n.t("all")}
+          {I18NextService.i18n.t("all")}
         </label>
       </div>
     );
index bdd42f38c35b6bf07ee6983edda3a13d1bcaf61d..97d1d1424d626f87327ea3c2f28beea78fe5fa10 100644 (file)
@@ -12,9 +12,8 @@ import {
   maxUploadImages,
   relTags,
 } from "../../config";
-import { i18n } from "../../i18next";
 import { customEmojisLookup, mdToHtml, setupTribute } from "../../markdown";
-import { HttpService, UserService } from "../../services";
+import { HttpService, I18NextService, UserService } from "../../services";
 import { setupTippy } from "../../tippy";
 import { pictrsDeleteToast, toast } from "../../toast";
 import { EmojiPicker } from "./emoji-picker";
@@ -129,7 +128,7 @@ export class MarkdownTextArea extends Component<
     // TODO add these prompts back in at some point
     // <Prompt
     //   when={!this.props.hideNavigationWarnings && this.state.content}
-    //   message={i18n.t("block_leaving")}
+    //   message={I18NextService.i18n.t("block_leaving")}
     // />
     return (
       <form
@@ -161,7 +160,7 @@ export class MarkdownTextArea extends Component<
                     className={`mb-0 ${
                       UserService.Instance.myUserInfo && "pointer"
                     }`}
-                    data-tippy-content={i18n.t("upload_image")}
+                    data-tippy-content={I18NextService.i18n.t("upload_image")}
                   >
                     {this.state.imageUploadStatus ? (
                       <Spinner />
@@ -199,7 +198,7 @@ export class MarkdownTextArea extends Component<
                 <a
                   href={markdownHelpUrl}
                   className="btn btn-sm text-muted font-weight-bold"
-                  title={i18n.t("formatting_help")}
+                  title={I18NextService.i18n.t("formatting_help")}
                   rel={relTags}
                 >
                   <Icon icon="help-circle" classes="icon-inline" />
@@ -241,15 +240,17 @@ export class MarkdownTextArea extends Component<
                       animated
                       value={this.state.imageUploadStatus.uploaded}
                       max={this.state.imageUploadStatus.total}
-                      text={i18n.t("pictures_uploded_progess", {
-                        uploaded: this.state.imageUploadStatus.uploaded,
-                        total: this.state.imageUploadStatus.total,
-                      })}
+                      text={
+                        I18NextService.i18n.t("pictures_uploded_progess", {
+                          uploaded: this.state.imageUploadStatus.uploaded,
+                          total: this.state.imageUploadStatus.total,
+                        }) ?? undefined
+                      }
                     />
                   )}
               </div>
               <label className="visually-hidden" htmlFor={this.id}>
-                {i18n.t("body")}
+                {I18NextService.i18n.t("body")}
               </label>
             </div>
           </div>
@@ -290,7 +291,7 @@ export class MarkdownTextArea extends Component<
                 className="btn btn-sm btn-secondary ms-2"
                 onClick={linkEvent(this, this.handleReplyCancel)}
               >
-                {i18n.t("cancel")}
+                {I18NextService.i18n.t("cancel")}
               </button>
             )}
             {this.state.content && (
@@ -300,7 +301,9 @@ export class MarkdownTextArea extends Component<
                 }`}
                 onClick={linkEvent(this, this.handlePreviewToggle)}
               >
-                {this.state.previewMode ? i18n.t("edit") : i18n.t("preview")}
+                {this.state.previewMode
+                  ? I18NextService.i18n.t("edit")
+                  : I18NextService.i18n.t("preview")}
               </button>
             )}
           </div>
@@ -332,8 +335,8 @@ export class MarkdownTextArea extends Component<
     return (
       <button
         className="btn btn-sm text-muted"
-        data-tippy-content={i18n.t(type)}
-        aria-label={i18n.t(type)}
+        data-tippy-content={I18NextService.i18n.t(type)}
+        aria-label={I18NextService.i18n.t(type)}
         onClick={linkEvent(this, handleClick)}
         disabled={this.isDisabled}
       >
@@ -376,7 +379,7 @@ export class MarkdownTextArea extends Component<
 
     if (files.length > maxUploadImages) {
       toast(
-        i18n.t("too_many_images_upload", {
+        I18NextService.i18n.t("too_many_images_upload", {
           count: Number(maxUploadImages),
           formattedCount: numToSI(maxUploadImages),
         }),
@@ -677,7 +680,7 @@ export class MarkdownTextArea extends Component<
 
   handleInsertSpoiler(i: MarkdownTextArea, event: any) {
     event.preventDefault();
-    const beforeChars = `\n::: spoiler ${i18n.t("spoiler")}\n`;
+    const beforeChars = `\n::: spoiler ${I18NextService.i18n.t("spoiler")}\n`;
     const afterChars = "\n:::\n";
     i.simpleSurroundBeforeAfter(beforeChars, afterChars);
   }
index 4df6c82e30e676d6c9c44eda639a488f9d4d9c6c..1857a0070c3cd133b598bc814172de2ef24f5aff 100644 (file)
@@ -1,7 +1,7 @@
 import { capitalizeFirstLetter } from "@utils/helpers";
 import { Component } from "inferno";
 import moment from "moment";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 import { Icon } from "./icon";
 
 interface MomentTimeProps {
@@ -15,18 +15,18 @@ export class MomentTime extends Component<MomentTimeProps, any> {
   constructor(props: any, context: any) {
     super(props, context);
 
-    moment.locale([...i18n.languages]);
+    moment.locale([...I18NextService.i18n.languages]);
   }
 
   createdAndModifiedTimes() {
     const updated = this.props.updated;
-    let line = `${capitalizeFirstLetter(i18n.t("created"))}: ${this.format(
-      this.props.published
-    )}`;
+    let line = `${capitalizeFirstLetter(
+      I18NextService.i18n.t("created")
+    )}: ${this.format(this.props.published)}`;
     if (updated) {
-      line += `\n\n\n${capitalizeFirstLetter(i18n.t("modified"))} ${this.format(
-        updated
-      )}`;
+      line += `\n\n\n${capitalizeFirstLetter(
+        I18NextService.i18n.t("modified")
+      )} ${this.format(updated)}`;
     }
     return line;
   }
index f76e69574bff07433635c51a10ae3b54c3f2a7d0..81ca87947ac01498f23a75ba8d147e4422b9eb03 100644 (file)
@@ -1,5 +1,5 @@
 import { Component } from "inferno";
-import { i18n } from "../../../shared/i18next";
+import { I18NextService } from "../../services";
 
 export interface IPromptProps {
   when: boolean;
@@ -14,7 +14,7 @@ export default class NavigationPrompt extends Component<IPromptProps, any> {
     }
 
     this.unblock = this.context.router.history.block(tx => {
-      if (window.confirm(i18n.t("block_leaving"))) {
+      if (window.confirm(I18NextService.i18n.t("block_leaving") ?? undefined)) {
         this.unblock();
         tx.retry();
       }
index 1ce38054e4991adca7b22569b761e7acfe2776f8..bd4ecf8752e48bb94ee4349e5d27fac1025a3806 100644 (file)
@@ -1,5 +1,5 @@
 import { Component, linkEvent } from "inferno";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 
 interface PaginatorProps {
   page: number;
@@ -18,13 +18,13 @@ export class Paginator extends Component<PaginatorProps, any> {
           disabled={this.props.page == 1}
           onClick={linkEvent(this, this.handlePrev)}
         >
-          {i18n.t("prev")}
+          {I18NextService.i18n.t("prev")}
         </button>
         <button
           className="btn btn-secondary"
           onClick={linkEvent(this, this.handleNext)}
         >
-          {i18n.t("next")}
+          {I18NextService.i18n.t("next")}
         </button>
       </div>
     );
index 6e6914b3fb616396f79fae51191a33334e4c63e9..3857c49ed1e903067d4becf6f3ed9d1010d10ae0 100644 (file)
@@ -5,8 +5,8 @@ import {
   ApproveRegistrationApplication,
   RegistrationApplicationView,
 } from "lemmy-js-client";
-import { i18n } from "../../i18next";
 import { mdToHtml } from "../../markdown";
+import { I18NextService } from "../../services";
 import { PersonListing } from "../person/person-listing";
 import { Spinner } from "./icon";
 import { MarkdownTextArea } from "./markdown-textarea";
@@ -61,12 +61,14 @@ export class RegistrationApplication extends Component<
     return (
       <div className="registration-application">
         <div>
-          {i18n.t("applicant")}: <PersonListing person={a.creator} />
+          {I18NextService.i18n.t("applicant")}:{" "}
+          <PersonListing person={a.creator} />
         </div>
         <div>
-          {i18n.t("created")}: <MomentTime showAgo published={ra.published} />
+          {I18NextService.i18n.t("created")}:{" "}
+          <MomentTime showAgo published={ra.published} />
         </div>
-        <div>{i18n.t("answer")}:</div>
+        <div>{I18NextService.i18n.t("answer")}:</div>
         <div className="md-div" dangerouslySetInnerHTML={mdToHtml(ra.answer)} />
 
         {a.admin && (
@@ -84,7 +86,7 @@ export class RegistrationApplication extends Component<
                 </T>
                 {ra.deny_reason && (
                   <div>
-                    {i18n.t("deny_reason")}:{" "}
+                    {I18NextService.i18n.t("deny_reason")}:{" "}
                     <div
                       className="md-div d-inline-flex"
                       dangerouslySetInnerHTML={mdToHtml(ra.deny_reason)}
@@ -99,7 +101,7 @@ export class RegistrationApplication extends Component<
         {this.state.denyExpanded && (
           <div className="mb-3 row">
             <label className="col-sm-2 col-form-label">
-              {i18n.t("deny_reason")}
+              {I18NextService.i18n.t("deny_reason")}
             </label>
             <div className="col-sm-10">
               <MarkdownTextArea
@@ -116,18 +118,26 @@ export class RegistrationApplication extends Component<
           <button
             className="btn btn-secondary me-2 my-2"
             onClick={linkEvent(this, this.handleApprove)}
-            aria-label={i18n.t("approve")}
+            aria-label={I18NextService.i18n.t("approve")}
           >
-            {this.state.approveLoading ? <Spinner /> : i18n.t("approve")}
+            {this.state.approveLoading ? (
+              <Spinner />
+            ) : (
+              I18NextService.i18n.t("approve")
+            )}
           </button>
         )}
         {(!ra.admin_id || (ra.admin_id && accepted)) && (
           <button
             className="btn btn-secondary me-2"
             onClick={linkEvent(this, this.handleDeny)}
-            aria-label={i18n.t("deny")}
+            aria-label={I18NextService.i18n.t("deny")}
           >
-            {this.state.denyLoading ? <Spinner /> : i18n.t("deny")}
+            {this.state.denyLoading ? (
+              <Spinner />
+            ) : (
+              I18NextService.i18n.t("deny")
+            )}
           </button>
         )}
       </div>
index cf3a0f6290c57ff6f288aad01f64dab56e5073f1..a29fe1606e49effa78f1c53488cbf5109afe565e 100644 (file)
@@ -7,7 +7,7 @@ import {
   linkEvent,
   RefObject,
 } from "inferno";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 import { Icon, Spinner } from "./icon";
 
 interface SearchableSelectProps {
@@ -113,7 +113,7 @@ export class SearchableSelect extends Component<
           ref={this.toggleButtonRef}
         >
           {loading
-            ? `${i18n.t("loading")}${loadingEllipses}`
+            ? `${I18NextService.i18n.t("loading")}${loadingEllipses}`
             : options[selectedIndex].label}
         </button>
         <div
@@ -131,7 +131,7 @@ export class SearchableSelect extends Component<
               ref={this.searchInputRef}
               onInput={linkEvent(this, handleSearch)}
               value={searchText}
-              placeholder={`${i18n.t("search")}...`}
+              placeholder={`${I18NextService.i18n.t("search")}...`}
             />
           </div>
           {!loading &&
index 546b3aec228a511adb68a1ebac636c5cb4e46d41..90515d5648992452114a0af158eb5d70ecdbfc5d 100644 (file)
@@ -2,7 +2,7 @@ import { randomStr } from "@utils/helpers";
 import { Component, linkEvent } from "inferno";
 import { SortType } from "lemmy-js-client";
 import { relTags, sortingHelpUrl } from "../../config";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 import { Icon } from "./icon";
 
 interface SortSelectProps {
@@ -41,43 +41,45 @@ export class SortSelect extends Component<SortSelectProps, SortSelectState> {
           value={this.state.sort}
           onChange={linkEvent(this, this.handleSortChange)}
           className="sort-select form-select d-inline-block w-auto me-2"
-          aria-label={i18n.t("sort_type")}
+          aria-label={I18NextService.i18n.t("sort_type")}
         >
           <option disabled aria-hidden="true">
-            {i18n.t("sort_type")}
+            {I18NextService.i18n.t("sort_type")}
           </option>
           {!this.props.hideHot && [
             <option key={"Hot"} value={"Hot"}>
-              {i18n.t("hot")}
+              {I18NextService.i18n.t("hot")}
             </option>,
             <option key={"Active"} value={"Active"}>
-              {i18n.t("active")}
+              {I18NextService.i18n.t("active")}
             </option>,
           ]}
-          <option value={"New"}>{i18n.t("new")}</option>
-          <option value={"Old"}>{i18n.t("old")}</option>
+          <option value={"New"}>{I18NextService.i18n.t("new")}</option>
+          <option value={"Old"}>{I18NextService.i18n.t("old")}</option>
           {!this.props.hideMostComments && [
             <option key={"MostComments"} value={"MostComments"}>
-              {i18n.t("most_comments")}
+              {I18NextService.i18n.t("most_comments")}
             </option>,
             <option key={"NewComments"} value={"NewComments"}>
-              {i18n.t("new_comments")}
+              {I18NextService.i18n.t("new_comments")}
             </option>,
           ]}
           <option disabled aria-hidden="true">
             ─────
           </option>
-          <option value={"TopDay"}>{i18n.t("top_day")}</option>
-          <option value={"TopWeek"}>{i18n.t("top_week")}</option>
-          <option value={"TopMonth"}>{i18n.t("top_month")}</option>
-          <option value={"TopYear"}>{i18n.t("top_year")}</option>
-          <option value={"TopAll"}>{i18n.t("top_all")}</option>
+          <option value={"TopDay"}>{I18NextService.i18n.t("top_day")}</option>
+          <option value={"TopWeek"}>{I18NextService.i18n.t("top_week")}</option>
+          <option value={"TopMonth"}>
+            {I18NextService.i18n.t("top_month")}
+          </option>
+          <option value={"TopYear"}>{I18NextService.i18n.t("top_year")}</option>
+          <option value={"TopAll"}>{I18NextService.i18n.t("top_all")}</option>
         </select>
         <a
           className="sort-select-icon text-muted"
           href={sortingHelpUrl}
           rel={relTags}
-          title={i18n.t("sorting_help")}
+          title={I18NextService.i18n.t("sorting_help")}
         >
           <Icon icon="help-circle" classes="icon-inline" />
         </a>
index 9a4e836a46c73647d28974267648512dd3af9d0a..a84ec055568a9394a768b265f2adc1f386bdc288 100644 (file)
@@ -21,9 +21,8 @@ import {
   ListCommunitiesResponse,
   ListingType,
 } from "lemmy-js-client";
-import { i18n } from "../../i18next";
 import { InitialFetchRequest } from "../../interfaces";
-import { FirstLoadService } from "../../services/FirstLoadService";
+import { FirstLoadService, I18NextService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
 import { HtmlTags } from "../common/html-tags";
 import { Spinner } from "../common/icon";
@@ -86,7 +85,7 @@ export class Communities extends Component<any, CommunitiesState> {
   }
 
   get documentTitle(): string {
-    return `${i18n.t("communities")} - ${
+    return `${I18NextService.i18n.t("communities")} - ${
       this.state.siteRes.site_view.site.name
     }`;
   }
@@ -103,7 +102,9 @@ export class Communities extends Component<any, CommunitiesState> {
         const { listingType, page } = this.getCommunitiesQueryParams();
         return (
           <div>
-            <h1 className="h4">{i18n.t("list_of_communities")}</h1>
+            <h1 className="h4">
+              {I18NextService.i18n.t("list_of_communities")}
+            </h1>
             <div className="row g-2 justify-content-between">
               <div className="col-auto">
                 <ListingTypeSelect
@@ -123,16 +124,19 @@ export class Communities extends Component<any, CommunitiesState> {
               >
                 <thead className="pointer">
                   <tr>
-                    <th>{i18n.t("name")}</th>
-                    <th className="text-right">{i18n.t("subscribers")}</th>
+                    <th>{I18NextService.i18n.t("name")}</th>
                     <th className="text-right">
-                      {i18n.t("users")} / {i18n.t("month")}
+                      {I18NextService.i18n.t("subscribers")}
+                    </th>
+                    <th className="text-right">
+                      {I18NextService.i18n.t("users")} /{" "}
+                      {I18NextService.i18n.t("month")}
                     </th>
                     <th className="text-right d-none d-lg-table-cell">
-                      {i18n.t("posts")}
+                      {I18NextService.i18n.t("posts")}
                     </th>
                     <th className="text-right d-none d-lg-table-cell">
-                      {i18n.t("comments")}
+                      {I18NextService.i18n.t("comments")}
                     </th>
                     <th></th>
                   </tr>
@@ -169,7 +173,7 @@ export class Communities extends Component<any, CommunitiesState> {
                                 this.handleFollow
                               )}
                             >
-                              {i18n.t("unsubscribe")}
+                              {I18NextService.i18n.t("unsubscribe")}
                             </button>
                           )}
                           {cv.subscribed === "NotSubscribed" && (
@@ -184,12 +188,12 @@ export class Communities extends Component<any, CommunitiesState> {
                                 this.handleFollow
                               )}
                             >
-                              {i18n.t("subscribe")}
+                              {I18NextService.i18n.t("subscribe")}
                             </button>
                           )}
                           {cv.subscribed === "Pending" && (
                             <div className="text-warning d-inline-block">
-                              {i18n.t("subscribe_pending")}
+                              {I18NextService.i18n.t("subscribe_pending")}
                             </div>
                           )}
                         </td>
@@ -230,7 +234,7 @@ export class Communities extends Component<any, CommunitiesState> {
             id="communities-search"
             className="form-control"
             value={this.state.searchText}
-            placeholder={`${i18n.t("search")}...`}
+            placeholder={`${I18NextService.i18n.t("search")}...`}
             onInput={linkEvent(this, this.handleSearchChange)}
             required
             minLength={3}
@@ -238,10 +242,10 @@ export class Communities extends Component<any, CommunitiesState> {
         </div>
         <div className="col-auto">
           <label className="visually-hidden" htmlFor="communities-search">
-            {i18n.t("search")}
+            {I18NextService.i18n.t("search")}
           </label>
           <button type="submit" className="btn btn-secondary">
-            <span>{i18n.t("search")}</span>
+            <span>{I18NextService.i18n.t("search")}</span>
           </button>
         </div>
       </form>
index ab19da82c87216d813e57e30ea5c1408f7f6bfae..6e2eba5ab702e59e18f319f9c8bc7bd5be854c75 100644 (file)
@@ -7,7 +7,7 @@ import {
   EditCommunity,
   Language,
 } from "lemmy-js-client";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 import { Icon, Spinner } from "../common/icon";
 import { ImageUploadForm } from "../common/image-upload-form";
 import { LanguageSelect } from "../common/language-select";
@@ -107,10 +107,10 @@ export class CommunityForm extends Component<
               className="col-12 col-sm-2 col-form-label"
               htmlFor="community-name"
             >
-              {i18n.t("name")}
+              {I18NextService.i18n.t("name")}
               <span
                 className="position-absolute pointer unselectable ms-2 text-muted"
-                data-tippy-content={i18n.t("name_explain")}
+                data-tippy-content={I18NextService.i18n.t("name_explain")}
               >
                 <Icon icon="help-circle" classes="icon-inline" />
               </span>
@@ -125,7 +125,7 @@ export class CommunityForm extends Component<
                 required
                 minLength={3}
                 pattern="[a-z0-9_]+"
-                title={i18n.t("community_reqs")}
+                title={I18NextService.i18n.t("community_reqs")}
               />
             </div>
           </div>
@@ -135,10 +135,10 @@ export class CommunityForm extends Component<
             className="col-12 col-sm-2 col-form-label"
             htmlFor="community-title"
           >
-            {i18n.t("display_name")}
+            {I18NextService.i18n.t("display_name")}
             <span
               className="position-absolute pointer unselectable ms-2 text-muted"
-              data-tippy-content={i18n.t("display_name_explain")}
+              data-tippy-content={I18NextService.i18n.t("display_name_explain")}
             >
               <Icon icon="help-circle" classes="icon-inline" />
             </span>
@@ -158,11 +158,11 @@ export class CommunityForm extends Component<
         </div>
         <div className="mb-3 row">
           <label className="col-12 col-sm-2 col-form-label">
-            {i18n.t("icon")}
+            {I18NextService.i18n.t("icon")}
           </label>
           <div className="col-12 col-sm-10">
             <ImageUploadForm
-              uploadTitle={i18n.t("upload_icon")}
+              uploadTitle={I18NextService.i18n.t("upload_icon")}
               imageSrc={this.state.form.icon}
               onUpload={this.handleIconUpload}
               onRemove={this.handleIconRemove}
@@ -172,11 +172,11 @@ export class CommunityForm extends Component<
         </div>
         <div className="mb-3 row">
           <label className="col-12 col-sm-2 col-form-label">
-            {i18n.t("banner")}
+            {I18NextService.i18n.t("banner")}
           </label>
           <div className="col-12 col-sm-10">
             <ImageUploadForm
-              uploadTitle={i18n.t("upload_banner")}
+              uploadTitle={I18NextService.i18n.t("upload_banner")}
               imageSrc={this.state.form.banner}
               onUpload={this.handleBannerUpload}
               onRemove={this.handleBannerRemove}
@@ -185,12 +185,12 @@ export class CommunityForm extends Component<
         </div>
         <div className="mb-3 row">
           <label className="col-12 col-sm-2 col-form-label" htmlFor={this.id}>
-            {i18n.t("sidebar")}
+            {I18NextService.i18n.t("sidebar")}
           </label>
           <div className="col-12 col-sm-10">
             <MarkdownTextArea
               initialContent={this.state.form.description}
-              placeholder={i18n.t("description")}
+              placeholder={I18NextService.i18n.t("description") ?? undefined}
               onContentChange={this.handleCommunityDescriptionChange}
               hideNavigationWarnings
               allLanguages={[]}
@@ -202,7 +202,7 @@ export class CommunityForm extends Component<
         {this.props.enableNsfw && (
           <div className="mb-3 row">
             <legend className="col-form-label col-sm-2 pt-0">
-              {i18n.t("nsfw")}
+              {I18NextService.i18n.t("nsfw")}
             </legend>
             <div className="col-10">
               <div className="form-check">
@@ -219,7 +219,7 @@ export class CommunityForm extends Component<
         )}
         <div className="mb-3 row">
           <legend className="col-form-label col-6 pt-0">
-            {i18n.t("only_mods_can_post_in_community")}
+            {I18NextService.i18n.t("only_mods_can_post_in_community")}
           </legend>
           <div className="col-6">
             <div className="form-check">
@@ -254,9 +254,9 @@ export class CommunityForm extends Component<
               {this.props.loading ? (
                 <Spinner />
               ) : this.props.community_view ? (
-                capitalizeFirstLetter(i18n.t("save"))
+                capitalizeFirstLetter(I18NextService.i18n.t("save"))
               ) : (
-                capitalizeFirstLetter(i18n.t("create"))
+                capitalizeFirstLetter(I18NextService.i18n.t("create"))
               )}
             </button>
             {this.props.community_view && (
@@ -265,7 +265,7 @@ export class CommunityForm extends Component<
                 className="btn btn-secondary"
                 onClick={linkEvent(this, this.handleCancel)}
               >
-                {i18n.t("cancel")}
+                {I18NextService.i18n.t("cancel")}
               </button>
             )}
           </div>
index 195ff687011463f96c8899e960e1b9991dc4ea26..7eefe0eb96ea0c8a2932e5b9f94d0bef371adf1f 100644 (file)
@@ -78,14 +78,12 @@ import {
   TransferCommunity,
 } from "lemmy-js-client";
 import { fetchLimit, relTags } from "../../config";
-import { i18n } from "../../i18next";
 import {
   CommentViewType,
   DataType,
   InitialFetchRequest,
 } from "../../interfaces";
-import { UserService } from "../../services";
-import { FirstLoadService } from "../../services/FirstLoadService";
+import { FirstLoadService, I18NextService, UserService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
 import { setupTippy } from "../../tippy";
 import { toast } from "../../toast";
@@ -331,7 +329,7 @@ export class Community extends Component<
                     className="btn btn-secondary d-inline-block mb-2 me-3"
                     onClick={linkEvent(this, this.handleShowSidebarMobile)}
                   >
-                    {i18n.t("sidebar")}{" "}
+                    {I18NextService.i18n.t("sidebar")}{" "}
                     <Icon
                       icon={
                         this.state.showSidebarMobile
@@ -758,14 +756,14 @@ export class Community extends Component<
   async handleCommentReport(form: CreateCommentReport) {
     const reportRes = await HttpService.client.createCommentReport(form);
     if (reportRes.state == "success") {
-      toast(i18n.t("report_created"));
+      toast(I18NextService.i18n.t("report_created"));
     }
   }
 
   async handlePostReport(form: CreatePostReport) {
     const reportRes = await HttpService.client.createPostReport(form);
     if (reportRes.state == "success") {
-      toast(i18n.t("report_created"));
+      toast(I18NextService.i18n.t("report_created"));
     }
   }
 
@@ -791,7 +789,7 @@ export class Community extends Component<
     const transferCommunityRes = await HttpService.client.transferCommunity(
       form
     );
-    toast(i18n.t("transfer_community"));
+    toast(I18NextService.i18n.t("transfer_community"));
     this.updateCommunityFull(transferCommunityRes);
   }
 
@@ -880,7 +878,7 @@ export class Community extends Component<
 
   purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
     if (purgeRes.state == "success") {
-      toast(i18n.t("purge_success"));
+      toast(I18NextService.i18n.t("purge_success"));
       this.context.router.history.push(`/`);
     }
   }
index 8a3b198512c6e5e0239d75145f6f9669143bbf0f..2ce5af5a67cf01037872e9693b2e6290d34273bd 100644 (file)
@@ -4,8 +4,7 @@ import {
   CreateCommunity as CreateCommunityI,
   GetSiteResponse,
 } from "lemmy-js-client";
-import { i18n } from "../../i18next";
-import { HttpService } from "../../services/HttpService";
+import { HttpService, I18NextService } from "../../services";
 import { HtmlTags } from "../common/html-tags";
 import { CommunityForm } from "./community-form";
 
@@ -26,7 +25,7 @@ export class CreateCommunity extends Component<any, CreateCommunityState> {
   }
 
   get documentTitle(): string {
-    return `${i18n.t("create_community")} - ${
+    return `${I18NextService.i18n.t("create_community")} - ${
       this.state.siteRes.site_view.site.name
     }`;
   }
@@ -40,7 +39,7 @@ export class CreateCommunity extends Component<any, CreateCommunityState> {
         />
         <div className="row">
           <div className="col-12 col-lg-6 offset-lg-3 mb-4">
-            <h5>{i18n.t("create_community")}</h5>
+            <h5>{I18NextService.i18n.t("create_community")}</h5>
             <CommunityForm
               onUpsertCommunity={this.handleCommunityCreate}
               enableNsfw={enableNsfw(this.state.siteRes)}
index 8bc54c02438ff57af9ac1c8fdcd1963012e7af1a..81a5dafc7a492a5369bb7d362c2ab927ea63b2d2 100644 (file)
@@ -17,9 +17,8 @@ import {
   PurgeCommunity,
   RemoveCommunity,
 } from "lemmy-js-client";
-import { i18n } from "../../i18next";
 import { mdToHtml } from "../../markdown";
-import { UserService } from "../../services";
+import { I18NextService, UserService } from "../../services";
 import { Badges } from "../common/badges";
 import { BannerIconHeader } from "../common/banner-icon-header";
 import { Icon, PurgeWarning, Spinner } from "../common/icon";
@@ -187,7 +186,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
               ) : (
                 <>
                   <Icon icon="check" classes="icon-inline text-success me-1" />
-                  {i18n.t("joined")}
+                  {I18NextService.i18n.t("joined")}
                 </>
               )}
             </button>
@@ -200,23 +199,23 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
               {this.state.followCommunityLoading ? (
                 <Spinner />
               ) : (
-                i18n.t("subscribe_pending")
+                I18NextService.i18n.t("subscribe_pending")
               )}
             </button>
           )}
           {community.removed && (
             <small className="me-2 text-muted font-italic">
-              {i18n.t("removed")}
+              {I18NextService.i18n.t("removed")}
             </small>
           )}
           {community.deleted && (
             <small className="me-2 text-muted font-italic">
-              {i18n.t("deleted")}
+              {I18NextService.i18n.t("deleted")}
             </small>
           )}
           {community.nsfw && (
             <small className="me-2 text-muted font-italic">
-              {i18n.t("nsfw")}
+              {I18NextService.i18n.t("nsfw")}
             </small>
           )}
         </h5>
@@ -234,7 +233,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
   mods() {
     return (
       <ul className="list-inline small">
-        <li className="list-inline-item">{i18n.t("mods")}: </li>
+        <li className="list-inline-item">{I18NextService.i18n.t("mods")}: </li>
         {this.props.moderators.map(mod => (
           <li key={mod.moderator.id} className="list-inline-item">
             <PersonListing person={mod.moderator} />
@@ -253,7 +252,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
         }`}
         to={`/create_post?communityId=${cv.community.id}`}
       >
-        {i18n.t("create_a_post")}
+        {I18NextService.i18n.t("create_a_post")}
       </Link>
     );
   }
@@ -270,7 +269,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
             {this.state.followCommunityLoading ? (
               <Spinner />
             ) : (
-              i18n.t("subscribe")
+              I18NextService.i18n.t("subscribe")
             )}
           </button>
         )}
@@ -288,7 +287,9 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
             className="btn btn-danger d-block mb-2 w-100"
             onClick={linkEvent(this, this.handleBlockCommunity)}
           >
-            {i18n.t(blocked ? "unblock_community" : "block_community")}
+            {I18NextService.i18n.t(
+              blocked ? "unblock_community" : "block_community"
+            )}
           </button>
         )}
       </>
@@ -315,8 +316,8 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
                 <button
                   className="btn btn-link text-muted d-inline-block"
                   onClick={linkEvent(this, this.handleEditClick)}
-                  data-tippy-content={i18n.t("edit")}
-                  aria-label={i18n.t("edit")}
+                  data-tippy-content={I18NextService.i18n.t("edit")}
+                  aria-label={I18NextService.i18n.t("edit")}
                 >
                   <Icon icon="edit" classes="icon-inline" />
                 </button>
@@ -331,20 +332,20 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
                         this.handleShowConfirmLeaveModTeamClick
                       )}
                     >
-                      {i18n.t("leave_mod_team")}
+                      {I18NextService.i18n.t("leave_mod_team")}
                     </button>
                   </li>
                 ) : (
                   <>
                     <li className="list-inline-item-action">
-                      {i18n.t("are_you_sure")}
+                      {I18NextService.i18n.t("are_you_sure")}
                     </li>
                     <li className="list-inline-item-action">
                       <button
                         className="btn btn-link text-muted d-inline-block"
                         onClick={linkEvent(this, this.handleLeaveModTeam)}
                       >
-                        {i18n.t("yes")}
+                        {I18NextService.i18n.t("yes")}
                       </button>
                     </li>
                     <li className="list-inline-item-action">
@@ -355,7 +356,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
                           this.handleCancelLeaveModTeamClick
                         )}
                       >
-                        {i18n.t("no")}
+                        {I18NextService.i18n.t("no")}
                       </button>
                     </li>
                   </>
@@ -367,13 +368,13 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
                     onClick={linkEvent(this, this.handleDeleteCommunity)}
                     data-tippy-content={
                       !community_view.community.deleted
-                        ? i18n.t("delete")
-                        : i18n.t("restore")
+                        ? I18NextService.i18n.t("delete")
+                        : I18NextService.i18n.t("restore")
                     }
                     aria-label={
                       !community_view.community.deleted
-                        ? i18n.t("delete")
-                        : i18n.t("restore")
+                        ? I18NextService.i18n.t("delete")
+                        : I18NextService.i18n.t("restore")
                     }
                   >
                     {this.state.deleteCommunityLoading ? (
@@ -398,7 +399,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
                   className="btn btn-link text-muted d-inline-block"
                   onClick={linkEvent(this, this.handleModRemoveShow)}
                 >
-                  {i18n.t("remove")}
+                  {I18NextService.i18n.t("remove")}
                 </button>
               ) : (
                 <button
@@ -408,16 +409,16 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
                   {this.state.removeCommunityLoading ? (
                     <Spinner />
                   ) : (
-                    i18n.t("restore")
+                    I18NextService.i18n.t("restore")
                   )}
                 </button>
               )}
               <button
                 className="btn btn-link text-muted d-inline-block"
                 onClick={linkEvent(this, this.handlePurgeCommunityShow)}
-                aria-label={i18n.t("purge_community")}
+                aria-label={I18NextService.i18n.t("purge_community")}
               >
-                {i18n.t("purge_community")}
+                {I18NextService.i18n.t("purge_community")}
               </button>
             </li>
           )}
@@ -426,13 +427,13 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
           <form onSubmit={linkEvent(this, this.handleRemoveCommunity)}>
             <div className="input-group mb-3">
               <label className="col-form-label" htmlFor="remove-reason">
-                {i18n.t("reason")}
+                {I18NextService.i18n.t("reason")}
               </label>
               <input
                 type="text"
                 id="remove-reason"
                 className="form-control me-2"
-                placeholder={i18n.t("optional")}
+                placeholder={I18NextService.i18n.t("optional")}
                 value={this.state.removeReason}
                 onInput={linkEvent(this, this.handleModRemoveReasonChange)}
               />
@@ -440,14 +441,14 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
             {/* TODO hold off on expires for now */}
             {/* <div class="mb-3 row"> */}
             {/*   <label class="col-form-label">Expires</label> */}
-            {/*   <input type="date" class="form-control me-2" placeholder={i18n.t('expires')} value={this.state.removeExpires} onInput={linkEvent(this, this.handleModRemoveExpiresChange)} /> */}
+            {/*   <input type="date" class="form-control me-2" placeholder={I18NextService.i18n.t('expires')} value={this.state.removeExpires} onInput={linkEvent(this, this.handleModRemoveExpiresChange)} /> */}
             {/* </div> */}
             <div className="input-group mb-3">
               <button type="submit" className="btn btn-secondary">
                 {this.state.removeCommunityLoading ? (
                   <Spinner />
                 ) : (
-                  i18n.t("remove_community")
+                  I18NextService.i18n.t("remove_community")
                 )}
               </button>
             </div>
@@ -460,13 +461,13 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
             </div>
             <div className="input-group mb-3">
               <label className="visually-hidden" htmlFor="purge-reason">
-                {i18n.t("reason")}
+                {I18NextService.i18n.t("reason")}
               </label>
               <input
                 type="text"
                 id="purge-reason"
                 className="form-control me-2"
-                placeholder={i18n.t("reason")}
+                placeholder={I18NextService.i18n.t("reason")}
                 value={this.state.purgeReason}
                 onInput={linkEvent(this, this.handlePurgeReasonChange)}
               />
@@ -478,9 +479,9 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
                 <button
                   type="submit"
                   className="btn btn-secondary"
-                  aria-label={i18n.t("purge_community")}
+                  aria-label={I18NextService.i18n.t("purge_community")}
                 >
-                  {i18n.t("purge_community")}
+                  {I18NextService.i18n.t("purge_community")}
                 </button>
               )}
             </div>
index 9b14310ce3e2f6cdd3b146aafb86aa5bcb5f903b..7ac69fedec5227662f03c0683116cafe47c1e864 100644 (file)
@@ -18,10 +18,9 @@ import {
   GetSiteResponse,
   PersonView,
 } from "lemmy-js-client";
-import { i18n } from "../../i18next";
 import { InitialFetchRequest } from "../../interfaces";
 import { removeFromEmojiDataModel, updateEmojiDataModel } from "../../markdown";
-import { FirstLoadService } from "../../services/FirstLoadService";
+import { FirstLoadService, I18NextService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
 import { toast } from "../../toast";
 import { HtmlTags } from "../common/html-tags";
@@ -108,7 +107,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
   }
 
   get documentTitle(): string {
-    return `${i18n.t("admin_settings")} - ${
+    return `${I18NextService.i18n.t("admin_settings")} - ${
       this.state.siteRes.site_view.site.name
     }`;
   }
@@ -129,7 +128,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
           tabs={[
             {
               key: "site",
-              label: i18n.t("site"),
+              label: I18NextService.i18n.t("site"),
               getNode: isSelected => (
                 <div
                   className={classNames("tab-pane show", {
@@ -181,7 +180,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
             },
             {
               key: "taglines",
-              label: i18n.t("taglines"),
+              label: I18NextService.i18n.t("taglines"),
               getNode: isSelected => (
                 <div
                   className={classNames("tab-pane", {
@@ -202,7 +201,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
             },
             {
               key: "emojis",
-              label: i18n.t("emojis"),
+              label: I18NextService.i18n.t("emojis"),
               getNode: isSelected => (
                 <div
                   className={classNames("tab-pane", {
@@ -253,7 +252,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
   admins() {
     return (
       <>
-        <h5>{capitalizeFirstLetter(i18n.t("admins"))}</h5>
+        <h5>{capitalizeFirstLetter(I18NextService.i18n.t("admins"))}</h5>
         <ul className="list-unstyled">
           {this.state.siteRes.admins.map(admin => (
             <li key={admin.person.id} className="list-inline-item">
@@ -275,7 +274,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
         {this.state.leaveAdminTeamRes.state == "loading" ? (
           <Spinner />
         ) : (
-          i18n.t("leave_admin_team")
+          I18NextService.i18n.t("leave_admin_team")
         )}
       </button>
     );
@@ -293,7 +292,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
         const bans = this.state.bannedRes.data.banned;
         return (
           <>
-            <h5>{i18n.t("banned_users")}</h5>
+            <h5>{I18NextService.i18n.t("banned_users")}</h5>
             <ul className="list-unstyled">
               {bans.map(banned => (
                 <li key={banned.person.id} className="list-inline-item">
@@ -319,7 +318,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
         s.siteRes.taglines = editRes.data.taglines;
         return s;
       });
-      toast(i18n.t("site_saved"));
+      toast(I18NextService.i18n.t("site_saved"));
     }
 
     this.setState({ loading: false });
@@ -340,7 +339,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
     });
 
     if (this.state.leaveAdminTeamRes.state === "success") {
-      toast(i18n.t("left_admin_team"));
+      toast(I18NextService.i18n.t("left_admin_team"));
       this.context.router.history.replace("/");
     }
   }
index 569abd0407df2891fa855ec1f8192d30b75e28aa..8428a54fe3454fa257ba7bfafaa7ad2af91cf821 100644 (file)
@@ -6,9 +6,8 @@ import {
   EditCustomEmoji,
   GetSiteResponse,
 } from "lemmy-js-client";
-import { i18n } from "../../i18next";
 import { customEmojisLookup } from "../../markdown";
-import { HttpService } from "../../services/HttpService";
+import { HttpService, I18NextService } from "../../services";
 import { pictrsDeleteToast, toast } from "../../toast";
 import { EmojiMart } from "../common/emoji-mart";
 import { HtmlTags } from "../common/html-tags";
@@ -66,7 +65,7 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
     this.handleEmojiClick = this.handleEmojiClick.bind(this);
   }
   get documentTitle(): string {
-    return i18n.t("custom_emojis");
+    return I18NextService.i18n.t("custom_emojis");
   }
 
   render() {
@@ -76,7 +75,7 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
           title={this.documentTitle}
           path={this.context.router.route.match.url}
         />
-        <h5 className="col-12">{i18n.t("custom_emojis")}</h5>
+        <h5 className="col-12">{I18NextService.i18n.t("custom_emojis")}</h5>
         {customEmojisLookup.size > 0 && (
           <div>
             <EmojiMart
@@ -89,15 +88,21 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
           <table id="emojis_table" className="table table-sm table-hover">
             <thead className="pointer">
               <tr>
-                <th>{i18n.t("column_emoji")}</th>
-                <th className="text-right">{i18n.t("column_shortcode")}</th>
-                <th className="text-right">{i18n.t("column_category")}</th>
+                <th>{I18NextService.i18n.t("column_emoji")}</th>
+                <th className="text-right">
+                  {I18NextService.i18n.t("column_shortcode")}
+                </th>
+                <th className="text-right">
+                  {I18NextService.i18n.t("column_category")}
+                </th>
                 <th className="text-right d-lg-table-cell d-none">
-                  {i18n.t("column_imageurl")}
+                  {I18NextService.i18n.t("column_imageurl")}
+                </th>
+                <th className="text-right">
+                  {I18NextService.i18n.t("column_alttext")}
                 </th>
-                <th className="text-right">{i18n.t("column_alttext")}</th>
                 <th className="text-right d-lg-table-cell">
-                  {i18n.t("column_keywords")}
+                  {I18NextService.i18n.t("column_keywords")}
                 </th>
                 <th style="width:121px"></th>
               </tr>
@@ -215,8 +220,8 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
                               { i: this, cv: cv },
                               this.handleEditEmojiClick
                             )}
-                            data-tippy-content={i18n.t("save")}
-                            aria-label={i18n.t("save")}
+                            data-tippy-content={I18NextService.i18n.t("save")}
+                            aria-label={I18NextService.i18n.t("save")}
                             disabled={
                               this.props.loading ||
                               !this.canEdit(cv) ||
@@ -236,10 +241,10 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
                             { i: this, index: index, cv: cv },
                             this.handleDeleteEmojiClick
                           )}
-                          data-tippy-content={i18n.t("delete")}
-                          aria-label={i18n.t("delete")}
+                          data-tippy-content={I18NextService.i18n.t("delete")}
+                          aria-label={I18NextService.i18n.t("delete")}
                           disabled={this.props.loading}
-                          title={i18n.t("delete")}
+                          title={I18NextService.i18n.t("delete")}
                         >
                           <Icon
                             icon="trash"
@@ -257,7 +262,7 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
             className="btn btn-sm btn-secondary me-2"
             onClick={linkEvent(this, this.handleAddEmojiClick)}
           >
-            {i18n.t("add_custom_emoji")}
+            {I18NextService.i18n.t("add_custom_emoji")}
           </button>
 
           <Paginator page={this.state.page} onChange={this.handlePageChange} />
@@ -280,8 +285,8 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
   }
 
   getEditTooltip(cv: CustomEmojiViewForm) {
-    if (this.canEdit(cv)) return i18n.t("save");
-    else return i18n.t("custom_emoji_save_validation");
+    if (this.canEdit(cv)) return I18NextService.i18n.t("save");
+    else return I18NextService.i18n.t("custom_emoji_save_validation");
   }
 
   handlePageChange(page: number) {
index a8441380aeab5d21f98a5c9c3fd516be2a0c4440..0d91bdbcc28815b0aaa427a2bc44c64e8ed33dff 100644 (file)
@@ -73,15 +73,13 @@ import {
   TransferCommunity,
 } from "lemmy-js-client";
 import { fetchLimit, relTags, trendingFetchLimit } from "../../config";
-import { i18n } from "../../i18next";
 import {
   CommentViewType,
   DataType,
   InitialFetchRequest,
 } from "../../interfaces";
 import { mdToHtml } from "../../markdown";
-import { UserService } from "../../services";
-import { FirstLoadService } from "../../services/FirstLoadService";
+import { FirstLoadService, I18NextService, UserService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
 import { setupTippy } from "../../tippy";
 import { toast } from "../../toast";
@@ -197,7 +195,7 @@ const MobileButton = ({
     className="btn btn-secondary d-inline-block mb-2 me-3"
     onClick={onClick}
   >
-    {i18n.t(textKey)}{" "}
+    {I18NextService.i18n.t(textKey)}{" "}
     <Icon icon={show ? `minus-square` : `plus-square`} classes="icon-inline" />
   </button>
 );
@@ -210,7 +208,7 @@ const LinkButton = ({
   translationKey: NoOptionI18nKeys;
 }) => (
   <Link className="btn btn-secondary d-block" to={path}>
-    {i18n.t(translationKey)}
+    {I18NextService.i18n.t(translationKey)}
   </Link>
 );
 
@@ -565,10 +563,14 @@ export class Home extends Component<any, HomeState> {
               className="btn btn-sm text-muted"
               onClick={linkEvent(this, this.handleCollapseSubscribe)}
               aria-label={
-                subscribedCollapsed ? i18n.t("expand") : i18n.t("collapse")
+                subscribedCollapsed
+                  ? I18NextService.i18n.t("expand")
+                  : I18NextService.i18n.t("collapse")
               }
               data-tippy-content={
-                subscribedCollapsed ? i18n.t("expand") : i18n.t("collapse")
+                subscribedCollapsed
+                  ? I18NextService.i18n.t("expand")
+                  : I18NextService.i18n.t("collapse")
               }
               aria-expanded="true"
               aria-controls="sidebarSubscribedBody"
@@ -932,14 +934,14 @@ export class Home extends Component<any, HomeState> {
   async handleCommentReport(form: CreateCommentReport) {
     const reportRes = await HttpService.client.createCommentReport(form);
     if (reportRes.state == "success") {
-      toast(i18n.t("report_created"));
+      toast(I18NextService.i18n.t("report_created"));
     }
   }
 
   async handlePostReport(form: CreatePostReport) {
     const reportRes = await HttpService.client.createPostReport(form);
     if (reportRes.state == "success") {
-      toast(i18n.t("report_created"));
+      toast(I18NextService.i18n.t("report_created"));
     }
   }
 
@@ -963,7 +965,7 @@ export class Home extends Component<any, HomeState> {
 
   async handleTransferCommunity(form: TransferCommunity) {
     await HttpService.client.transferCommunity(form);
-    toast(i18n.t("transfer_community"));
+    toast(I18NextService.i18n.t("transfer_community"));
   }
 
   async handleCommentReplyRead(form: MarkCommentReplyAsRead) {
@@ -1030,7 +1032,7 @@ export class Home extends Component<any, HomeState> {
 
   purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
     if (purgeRes.state == "success") {
-      toast(i18n.t("purge_success"));
+      toast(I18NextService.i18n.t("purge_success"));
       this.context.router.history.push(`/`);
     }
   }
index aba71099323ef4983f4e9ea843cbb824183cf899..b54c96af332dd045f7ab142e46c881a82e6123c9 100644 (file)
@@ -7,9 +7,8 @@ import {
   Instance,
 } from "lemmy-js-client";
 import { relTags } from "../../config";
-import { i18n } from "../../i18next";
 import { InitialFetchRequest } from "../../interfaces";
-import { FirstLoadService } from "../../services/FirstLoadService";
+import { FirstLoadService, I18NextService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
 import { HtmlTags } from "../common/html-tags";
 import { Spinner } from "../common/icon";
@@ -70,7 +69,9 @@ export class Instances extends Component<any, InstancesState> {
   }
 
   get documentTitle(): string {
-    return `${i18n.t("instances")} - ${this.state.siteRes.site_view.site.name}`;
+    return `${I18NextService.i18n.t("instances")} - ${
+      this.state.siteRes.site_view.site.name
+    }`;
   }
 
   renderInstances() {
@@ -86,18 +87,18 @@ export class Instances extends Component<any, InstancesState> {
         return instances ? (
           <div className="row">
             <div className="col-md-6">
-              <h5>{i18n.t("linked_instances")}</h5>
+              <h5>{I18NextService.i18n.t("linked_instances")}</h5>
               {this.itemList(instances.linked)}
             </div>
             {instances.allowed && instances.allowed.length > 0 && (
               <div className="col-md-6">
-                <h5>{i18n.t("allowed_instances")}</h5>
+                <h5>{I18NextService.i18n.t("allowed_instances")}</h5>
                 {this.itemList(instances.allowed)}
               </div>
             )}
             {instances.blocked && instances.blocked.length > 0 && (
               <div className="col-md-6">
-                <h5>{i18n.t("blocked_instances")}</h5>
+                <h5>{I18NextService.i18n.t("blocked_instances")}</h5>
                 {this.itemList(instances.blocked)}
               </div>
             )}
@@ -127,9 +128,9 @@ export class Instances extends Component<any, InstancesState> {
         <table id="instances_table" className="table table-sm table-hover">
           <thead className="pointer">
             <tr>
-              <th>{i18n.t("name")}</th>
-              <th>{i18n.t("software")}</th>
-              <th>{i18n.t("version")}</th>
+              <th>{I18NextService.i18n.t("name")}</th>
+              <th>{I18NextService.i18n.t("software")}</th>
+              <th>{I18NextService.i18n.t("version")}</th>
             </tr>
           </thead>
           <tbody>
@@ -148,7 +149,7 @@ export class Instances extends Component<any, InstancesState> {
         </table>
       </div>
     ) : (
-      <div>{i18n.t("none_found")}</div>
+      <div>{I18NextService.i18n.t("none_found")}</div>
     );
   }
 }
index 90c461a8d94d8848edec76cb64dab979e6e4a33f..85a413ebb9d4a5edecbbde00021dd079196a12a2 100644 (file)
@@ -1,8 +1,8 @@
 import { setIsoData } from "@utils/app";
 import { Component } from "inferno";
 import { GetSiteResponse } from "lemmy-js-client";
-import { i18n } from "../../i18next";
 import { mdToHtml } from "../../markdown";
+import { I18NextService } from "../../services";
 import { HtmlTags } from "../common/html-tags";
 
 interface LegalState {
@@ -20,7 +20,7 @@ export class Legal extends Component<any, LegalState> {
   }
 
   get documentTitle(): string {
-    return i18n.t("legal_information");
+    return I18NextService.i18n.t("legal_information");
   }
 
   render() {
index 3d602f916ddac3c4bed94d9e74d1eae84a1b0b61..1853a82b92d3c1b096ab7265c126d50a5a40e36e 100644 (file)
@@ -3,8 +3,7 @@ import { isBrowser } from "@utils/browser";
 import { validEmail } from "@utils/helpers";
 import { Component, linkEvent } from "inferno";
 import { GetSiteResponse, LoginResponse } from "lemmy-js-client";
-import { i18n } from "../../i18next";
-import { UserService } from "../../services";
+import { I18NextService, UserService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
 import { toast } from "../../toast";
 import { HtmlTags } from "../common/html-tags";
@@ -43,7 +42,9 @@ export class Login extends Component<any, State> {
   }
 
   get documentTitle(): string {
-    return `${i18n.t("login")} - ${this.state.siteRes.site_view.site.name}`;
+    return `${I18NextService.i18n.t("login")} - ${
+      this.state.siteRes.site_view.site.name
+    }`;
   }
 
   get isLemmyMl(): boolean {
@@ -68,13 +69,13 @@ export class Login extends Component<any, State> {
     return (
       <div>
         <form onSubmit={linkEvent(this, this.handleLoginSubmit)}>
-          <h5>{i18n.t("login")}</h5>
+          <h5>{I18NextService.i18n.t("login")}</h5>
           <div className="mb-3 row">
             <label
               className="col-sm-2 col-form-label"
               htmlFor="login-email-or-username"
             >
-              {i18n.t("email_or_username")}
+              {I18NextService.i18n.t("email_or_username")}
             </label>
             <div className="col-sm-10">
               <input
@@ -91,7 +92,7 @@ export class Login extends Component<any, State> {
           </div>
           <div className="mb-3 row">
             <label className="col-sm-2 col-form-label" htmlFor="login-password">
-              {i18n.t("password")}
+              {I18NextService.i18n.t("password")}
             </label>
             <div className="col-sm-10">
               <input
@@ -112,9 +113,9 @@ export class Login extends Component<any, State> {
                   !!this.state.form.username_or_email &&
                   !validEmail(this.state.form.username_or_email)
                 }
-                title={i18n.t("no_password_reset")}
+                title={I18NextService.i18n.t("no_password_reset")}
               >
-                {i18n.t("forgot_password")}
+                {I18NextService.i18n.t("forgot_password")}
               </button>
             </div>
           </div>
@@ -124,7 +125,7 @@ export class Login extends Component<any, State> {
                 className="col-sm-6 col-form-label"
                 htmlFor="login-totp-token"
               >
-                {i18n.t("two_factor_token")}
+                {I18NextService.i18n.t("two_factor_token")}
               </label>
               <div className="col-sm-6">
                 <input
@@ -146,7 +147,7 @@ export class Login extends Component<any, State> {
                 {this.state.loginRes.state == "loading" ? (
                   <Spinner />
                 ) : (
-                  i18n.t("login")
+                  I18NextService.i18n.t("login")
                 )}
               </button>
             </div>
@@ -172,7 +173,7 @@ export class Login extends Component<any, State> {
         case "failed": {
           if (loginRes.msg === "missing_totp_token") {
             i.setState({ showTotp: true });
-            toast(i18n.t("enter_two_factor_code"), "info");
+            toast(I18NextService.i18n.t("enter_two_factor_code"), "info");
           }
 
           i.setState({ loginRes: { state: "failed", msg: loginRes.msg } });
@@ -220,7 +221,7 @@ export class Login extends Component<any, State> {
     if (email) {
       const res = await HttpService.client.passwordReset({ email });
       if (res.state == "success") {
-        toast(i18n.t("reset_password_mail_sent"));
+        toast(I18NextService.i18n.t("reset_password_mail_sent"));
       }
     }
   }
index 619e70d8dd501b2adfce1616e2364d6c561b1f13..9003962a93fed223fdfd35d640200a0061e705ad 100644 (file)
@@ -3,7 +3,7 @@ import { capitalizeFirstLetter } from "@utils/helpers";
 import classNames from "classnames";
 import { Component, FormEventHandler, linkEvent } from "inferno";
 import { EditSite, LocalSiteRateLimit } from "lemmy-js-client";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 import { Spinner } from "../common/icon";
 import Tabs from "../common/tabs";
 
@@ -57,7 +57,9 @@ function RateLimits({
   return (
     <div role="tabpanel" className={classNames("mb-3 row", className)}>
       <div className="col-md-6">
-        <label htmlFor="rate-limit">{i18n.t("rate_limit")}</label>
+        <label htmlFor="rate-limit">
+          {I18NextService.i18n.t("rate_limit")}
+        </label>
         <input
           type="number"
           id="rate-limit"
@@ -68,7 +70,9 @@ function RateLimits({
         />
       </div>
       <div className="col-md-6">
-        <label htmlFor="rate-limit-per-second">{i18n.t("per_second")}</label>
+        <label htmlFor="rate-limit-per-second">
+          {I18NextService.i18n.t("per_second")}
+        </label>
         <input
           type="number"
           id="rate-limit-per-second"
@@ -141,11 +145,11 @@ export default class RateLimitsForm extends Component<
         className="rate-limit-form"
         onSubmit={linkEvent(this, submitRateLimitForm)}
       >
-        <h5>{i18n.t("rate_limit_header")}</h5>
+        <h5>{I18NextService.i18n.t("rate_limit_header")}</h5>
         <Tabs
           tabs={rateLimitTypes.map(rateLimitType => ({
             key: rateLimitType,
-            label: i18n.t(`rate_limit_${rateLimitType}`),
+            label: I18NextService.i18n.t(`rate_limit_${rateLimitType}`),
             getNode: isSelected => (
               <RateLimits
                 className={classNames("tab-pane show", {
@@ -176,7 +180,7 @@ export default class RateLimitsForm extends Component<
             {this.props.loading ? (
               <Spinner />
             ) : (
-              capitalizeFirstLetter(i18n.t("save"))
+              capitalizeFirstLetter(I18NextService.i18n.t("save"))
             )}
           </button>
         </div>
index b595e14d65f3975617af42d2d792976eec624034..bed1262038eb2a098724e07405c0ece852e1a520 100644 (file)
@@ -7,8 +7,7 @@ import {
   LoginResponse,
   Register,
 } from "lemmy-js-client";
-import { i18n } from "../../i18next";
-import { UserService } from "../../services";
+import { I18NextService, UserService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
 import { Spinner } from "../common/icon";
 import { SiteForm } from "./site-form";
@@ -55,7 +54,7 @@ export class Setup extends Component<any, State> {
   }
 
   get documentTitle(): string {
-    return `${i18n.t("setup")} - Lemmy`;
+    return `${I18NextService.i18n.t("setup")} - Lemmy`;
   }
 
   render() {
@@ -64,7 +63,7 @@ export class Setup extends Component<any, State> {
         <Helmet title={this.documentTitle} />
         <div className="row">
           <div className="col-12 offset-lg-3 col-lg-6">
-            <h3>{i18n.t("lemmy_instance_setup")}</h3>
+            <h3>{I18NextService.i18n.t("lemmy_instance_setup")}</h3>
             {!this.state.doneRegisteringUser ? (
               this.registerUser()
             ) : (
@@ -85,10 +84,10 @@ export class Setup extends Component<any, State> {
   registerUser() {
     return (
       <form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
-        <h5>{i18n.t("setup_admin")}</h5>
+        <h5>{I18NextService.i18n.t("setup_admin")}</h5>
         <div className="mb-3 row">
           <label className="col-sm-2 col-form-label" htmlFor="username">
-            {i18n.t("username")}
+            {I18NextService.i18n.t("username")}
           </label>
           <div className="col-sm-10">
             <input
@@ -105,7 +104,7 @@ export class Setup extends Component<any, State> {
         </div>
         <div className="mb-3 row">
           <label className="col-sm-2 col-form-label" htmlFor="email">
-            {i18n.t("email")}
+            {I18NextService.i18n.t("email")}
           </label>
 
           <div className="col-sm-10">
@@ -113,7 +112,7 @@ export class Setup extends Component<any, State> {
               type="email"
               id="email"
               className="form-control"
-              placeholder={i18n.t("optional")}
+              placeholder={I18NextService.i18n.t("optional")}
               value={this.state.form.email}
               onInput={linkEvent(this, this.handleRegisterEmailChange)}
               minLength={3}
@@ -122,7 +121,7 @@ export class Setup extends Component<any, State> {
         </div>
         <div className="mb-3 row">
           <label className="col-sm-2 col-form-label" htmlFor="password">
-            {i18n.t("password")}
+            {I18NextService.i18n.t("password")}
           </label>
           <div className="col-sm-10">
             <input
@@ -140,7 +139,7 @@ export class Setup extends Component<any, State> {
         </div>
         <div className="mb-3 row">
           <label className="col-sm-2 col-form-label" htmlFor="verify-password">
-            {i18n.t("verify_password")}
+            {I18NextService.i18n.t("verify_password")}
           </label>
           <div className="col-sm-10">
             <input
@@ -162,7 +161,7 @@ export class Setup extends Component<any, State> {
               {this.state.registerRes.state == "loading" ? (
                 <Spinner />
               ) : (
-                i18n.t("sign_up")
+                I18NextService.i18n.t("sign_up")
               )}
             </button>
           </div>
index 817dcf8c888a8a5a9d9602c5ff5b1421639d8133..a2d960dc675a5ba10f973e44e1673e9c5d73cb83 100644 (file)
@@ -13,9 +13,8 @@ import {
   SiteView,
 } from "lemmy-js-client";
 import { joinLemmyUrl } from "../../config";
-import { i18n } from "../../i18next";
 import { mdToHtml } from "../../markdown";
-import { UserService } from "../../services";
+import { I18NextService, UserService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
 import { toast } from "../../toast";
 import { HtmlTags } from "../common/html-tags";
@@ -113,7 +112,7 @@ export class Signup extends Component<any, State> {
   }
 
   titleName(siteView: SiteView): string {
-    return i18n.t(
+    return I18NextService.i18n.t(
       siteView.local_site.private_instance ? "apply_to_join" : "sign_up"
     );
   }
@@ -159,7 +158,7 @@ export class Signup extends Component<any, State> {
             className="col-sm-2 col-form-label"
             htmlFor="register-username"
           >
-            {i18n.t("username")}
+            {I18NextService.i18n.t("username")}
           </label>
 
           <div className="col-sm-10">
@@ -172,14 +171,14 @@ export class Signup extends Component<any, State> {
               required
               minLength={3}
               pattern="[a-zA-Z0-9_]+"
-              title={i18n.t("community_reqs")}
+              title={I18NextService.i18n.t("community_reqs")}
             />
           </div>
         </div>
 
         <div className="mb-3 row">
           <label className="col-sm-2 col-form-label" htmlFor="register-email">
-            {i18n.t("email")}
+            {I18NextService.i18n.t("email")}
           </label>
           <div className="col-sm-10">
             <input
@@ -188,8 +187,8 @@ export class Signup extends Component<any, State> {
               className="form-control"
               placeholder={
                 siteView.local_site.require_email_verification
-                  ? i18n.t("required")
-                  : i18n.t("optional")
+                  ? I18NextService.i18n.t("required")
+                  : I18NextService.i18n.t("optional")
               }
               value={this.state.form.email}
               autoComplete="email"
@@ -202,7 +201,7 @@ export class Signup extends Component<any, State> {
               !validEmail(this.state.form.email) && (
                 <div className="mt-2 mb-0 alert alert-warning" role="alert">
                   <Icon icon="alert-triangle" classes="icon-inline me-2" />
-                  {i18n.t("no_password_reset")}
+                  {I18NextService.i18n.t("no_password_reset")}
                 </div>
               )}
           </div>
@@ -213,7 +212,7 @@ export class Signup extends Component<any, State> {
             className="col-sm-2 col-form-label"
             htmlFor="register-password"
           >
-            {i18n.t("password")}
+            {I18NextService.i18n.t("password")}
           </label>
           <div className="col-sm-10">
             <input
@@ -229,7 +228,9 @@ export class Signup extends Component<any, State> {
             />
             {this.state.form.password && (
               <div className={this.passwordColorClass}>
-                {i18n.t(this.passwordStrength as NoOptionI18nKeys)}
+                {I18NextService.i18n.t(
+                  this.passwordStrength as NoOptionI18nKeys
+                )}
               </div>
             )}
           </div>
@@ -240,7 +241,7 @@ export class Signup extends Component<any, State> {
             className="col-sm-2 col-form-label"
             htmlFor="register-verify-password"
           >
-            {i18n.t("verify_password")}
+            {I18NextService.i18n.t("verify_password")}
           </label>
           <div className="col-sm-10">
             <input
@@ -262,7 +263,7 @@ export class Signup extends Component<any, State> {
               <div className="offset-sm-2 col-sm-10">
                 <div className="mt-2 alert alert-warning" role="alert">
                   <Icon icon="alert-triangle" classes="icon-inline me-2" />
-                  {i18n.t("fill_out_application")}
+                  {I18NextService.i18n.t("fill_out_application")}
                 </div>
                 {siteView.local_site.application_question && (
                   <div
@@ -280,7 +281,7 @@ export class Signup extends Component<any, State> {
                 className="col-sm-2 col-form-label"
                 htmlFor="application_answer"
               >
-                {i18n.t("answer")}
+                {I18NextService.i18n.t("answer")}
               </label>
               <div className="col-sm-10">
                 <MarkdownTextArea
@@ -306,7 +307,7 @@ export class Signup extends Component<any, State> {
                 onChange={linkEvent(this, this.handleRegisterShowNsfwChange)}
               />
               <label className="form-check-label" htmlFor="register-show-nsfw">
-                {i18n.t("show_nsfw")}
+                {I18NextService.i18n.t("show_nsfw")}
               </label>
             </div>
           </div>
@@ -345,12 +346,14 @@ export class Signup extends Component<any, State> {
         return (
           <div className="mb-3 row">
             <label className="col-sm-2" htmlFor="register-captcha">
-              <span className="me-2">{i18n.t("enter_code")}</span>
+              <span className="me-2">
+                {I18NextService.i18n.t("enter_code")}
+              </span>
               <button
                 type="button"
                 className="btn btn-secondary"
                 onClick={linkEvent(this, this.handleRegenCaptcha)}
-                aria-label={i18n.t("captcha")}
+                aria-label={I18NextService.i18n.t("captcha")}
               >
                 <Icon icon="refresh-cw" classes="icon-refresh-cw" />
               </button>
@@ -384,13 +387,13 @@ export class Signup extends Component<any, State> {
             className="rounded-top img-fluid"
             src={this.captchaPngSrc(captchaRes)}
             style="border-bottom-right-radius: 0; border-bottom-left-radius: 0;"
-            alt={i18n.t("captcha")}
+            alt={I18NextService.i18n.t("captcha")}
           />
           {captchaRes.wav && (
             <button
               className="rounded-bottom btn btn-sm btn-secondary d-block"
               style="border-top-right-radius: 0; border-top-left-radius: 0;"
-              title={i18n.t("play_captcha_audio")}
+              title={I18NextService.i18n.t("play_captcha_audio")}
               onClick={linkEvent(this, this.handleCaptchaPlay)}
               type="button"
               disabled={this.state.captchaPlaying}
@@ -474,10 +477,10 @@ export class Signup extends Component<any, State> {
             i.props.history.replace("/communities");
           } else {
             if (data.verify_email_sent) {
-              toast(i18n.t("verify_email_sent"));
+              toast(I18NextService.i18n.t("verify_email_sent"));
             }
             if (data.registration_created) {
-              toast(i18n.t("registration_application_sent"));
+              toast(I18NextService.i18n.t("registration_application_sent"));
             }
             i.props.history.push("/");
           }
index eb30cbe192dcc991ed4c5f8332d6f50c078a06b0..33e7989347ca128d68f1b0a3bd23b116a73bf981 100644 (file)
@@ -13,7 +13,7 @@ import {
   Instance,
   ListingType,
 } from "lemmy-js-client";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 import { Icon, Spinner } from "../common/icon";
 import { ImageUploadForm } from "../common/image-upload-form";
 import { LanguageSelect } from "../common/language-select";
@@ -136,12 +136,12 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
         />
         <h5>{`${
           siteSetup
-            ? capitalizeFirstLetter(i18n.t("edit"))
-            : capitalizeFirstLetter(i18n.t("setup"))
-        } ${i18n.t("your_site")}`}</h5>
+            ? capitalizeFirstLetter(I18NextService.i18n.t("edit"))
+            : capitalizeFirstLetter(I18NextService.i18n.t("setup"))
+        } ${I18NextService.i18n.t("your_site")}`}</h5>
         <div className="mb-3 row">
           <label className="col-12 col-form-label" htmlFor="create-site-name">
-            {i18n.t("name")}
+            {I18NextService.i18n.t("name")}
           </label>
           <div className="col-12">
             <input
@@ -157,9 +157,11 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
           </div>
         </div>
         <div className="input-group mb-3">
-          <label className="me-2 col-form-label">{i18n.t("icon")}</label>
+          <label className="me-2 col-form-label">
+            {I18NextService.i18n.t("icon")}
+          </label>
           <ImageUploadForm
-            uploadTitle={i18n.t("upload_icon")}
+            uploadTitle={I18NextService.i18n.t("upload_icon")}
             imageSrc={this.state.siteForm.icon}
             onUpload={this.handleIconUpload}
             onRemove={this.handleIconRemove}
@@ -167,9 +169,11 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
           />
         </div>
         <div className="input-group mb-3">
-          <label className="me-2 col-form-label">{i18n.t("banner")}</label>
+          <label className="me-2 col-form-label">
+            {I18NextService.i18n.t("banner")}
+          </label>
           <ImageUploadForm
-            uploadTitle={i18n.t("upload_banner")}
+            uploadTitle={I18NextService.i18n.t("upload_banner")}
             imageSrc={this.state.siteForm.banner}
             onUpload={this.handleBannerUpload}
             onRemove={this.handleBannerRemove}
@@ -177,7 +181,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
         </div>
         <div className="mb-3 row">
           <label className="col-12 col-form-label" htmlFor="site-desc">
-            {i18n.t("description")}
+            {I18NextService.i18n.t("description")}
           </label>
           <div className="col-12">
             <input
@@ -191,7 +195,9 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
           </div>
         </div>
         <div className="mb-3 row">
-          <label className="col-12 col-form-label">{i18n.t("sidebar")}</label>
+          <label className="col-12 col-form-label">
+            {I18NextService.i18n.t("sidebar")}
+          </label>
           <div className="col-12">
             <MarkdownTextArea
               initialContent={this.state.siteForm.sidebar}
@@ -204,7 +210,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
         </div>
         <div className="mb-3 row">
           <label className="col-12 col-form-label">
-            {i18n.t("legal_information")}
+            {I18NextService.i18n.t("legal_information")}
           </label>
           <div className="col-12">
             <MarkdownTextArea
@@ -230,7 +236,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
                 className="form-check-label"
                 htmlFor="create-site-downvotes"
               >
-                {i18n.t("enable_downvotes")}
+                {I18NextService.i18n.t("enable_downvotes")}
               </label>
             </div>
           </div>
@@ -249,7 +255,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
                 className="form-check-label"
                 htmlFor="create-site-enable-nsfw"
               >
-                {i18n.t("enable_nsfw")}
+                {I18NextService.i18n.t("enable_nsfw")}
               </label>
             </div>
           </div>
@@ -260,7 +266,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
               className="form-check-label me-2"
               htmlFor="create-site-registration-mode"
             >
-              {i18n.t("registration_mode")}
+              {I18NextService.i18n.t("registration_mode")}
             </label>
             <select
               id="create-site-registration-mode"
@@ -269,17 +275,21 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
               className="form-select d-inline-block w-auto"
             >
               <option value={"RequireApplication"}>
-                {i18n.t("require_registration_application")}
+                {I18NextService.i18n.t("require_registration_application")}
+              </option>
+              <option value={"Open"}>
+                {I18NextService.i18n.t("open_registration")}
+              </option>
+              <option value={"Closed"}>
+                {I18NextService.i18n.t("close_registration")}
               </option>
-              <option value={"Open"}>{i18n.t("open_registration")}</option>
-              <option value={"Closed"}>{i18n.t("close_registration")}</option>
             </select>
           </div>
         </div>
         {this.state.siteForm.registration_mode == "RequireApplication" && (
           <div className="mb-3 row">
             <label className="col-12 col-form-label">
-              {i18n.t("application_questionnaire")}
+              {I18NextService.i18n.t("application_questionnaire")}
             </label>
             <div className="col-12">
               <MarkdownTextArea
@@ -309,7 +319,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
                 className="form-check-label"
                 htmlFor="create-site-community-creation-admin-only"
               >
-                {i18n.t("community_creation_admin_only")}
+                {I18NextService.i18n.t("community_creation_admin_only")}
               </label>
             </div>
           </div>
@@ -331,7 +341,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
                 className="form-check-label"
                 htmlFor="create-site-require-email-verification"
               >
-                {i18n.t("require_email_verification")}
+                {I18NextService.i18n.t("require_email_verification")}
               </label>
             </div>
           </div>
@@ -353,7 +363,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
                 className="form-check-label"
                 htmlFor="create-site-email-admins"
               >
-                {i18n.t("application_email_admins")}
+                {I18NextService.i18n.t("application_email_admins")}
               </label>
             </div>
           </div>
@@ -372,7 +382,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
                 className="form-check-label"
                 htmlFor="create-site-reports-email-admins"
               >
-                {i18n.t("reports_email_admins")}
+                {I18NextService.i18n.t("reports_email_admins")}
               </label>
             </div>
           </div>
@@ -383,7 +393,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
               className="form-check-label me-2"
               htmlFor="create-site-default-theme"
             >
-              {i18n.t("theme")}
+              {I18NextService.i18n.t("theme")}
             </label>
             <select
               id="create-site-default-theme"
@@ -391,7 +401,9 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
               onChange={linkEvent(this, this.handleSiteDefaultTheme)}
               className="form-select d-inline-block w-auto"
             >
-              <option value="browser">{i18n.t("browser_default")}</option>
+              <option value="browser">
+                {I18NextService.i18n.t("browser_default")}
+              </option>
               {this.props.themeList?.map(theme => (
                 <option key={theme} value={theme}>
                   {theme}
@@ -403,7 +415,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
         {this.props.showLocal && (
           <form className="mb-3 row">
             <label className="col-sm-3 col-form-label">
-              {i18n.t("listing_type")}
+              {I18NextService.i18n.t("listing_type")}
             </label>
             <div className="col-sm-9">
               <ListingTypeSelect
@@ -429,7 +441,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
                 className="form-check-label"
                 htmlFor="create-site-private-instance"
               >
-                {i18n.t("private_instance")}
+                {I18NextService.i18n.t("private_instance")}
               </label>
             </div>
           </div>
@@ -448,7 +460,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
                 className="form-check-label"
                 htmlFor="create-site-hide-modlog-mod-names"
               >
-                {i18n.t("hide_modlog_mod_names")}
+                {I18NextService.i18n.t("hide_modlog_mod_names")}
               </label>
             </div>
           </div>
@@ -458,7 +470,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
             className="col-12 col-form-label"
             htmlFor="create-site-slur-filter-regex"
           >
-            {i18n.t("slur_filter_regex")}
+            {I18NextService.i18n.t("slur_filter_regex")}
           </label>
           <div className="col-12">
             <input
@@ -485,7 +497,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
             className="col-12 col-form-label"
             htmlFor="create-site-actor-name"
           >
-            {i18n.t("actor_name_max_length")}
+            {I18NextService.i18n.t("actor_name_max_length")}
           </label>
           <div className="col-12">
             <input
@@ -512,7 +524,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
                 className="form-check-label"
                 htmlFor="create-site-federation-enabled"
               >
-                {i18n.t("federation_enabled")}
+                {I18NextService.i18n.t("federation_enabled")}
               </label>
             </div>
           </div>
@@ -537,7 +549,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
                     className="form-check-label"
                     htmlFor="create-site-federation-debug"
                   >
-                    {i18n.t("federation_debug")}
+                    {I18NextService.i18n.t("federation_debug")}
                   </label>
                 </div>
               </div>
@@ -547,7 +559,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
                 className="col-12 col-form-label"
                 htmlFor="create-site-federation-worker-count"
               >
-                {i18n.t("federation_worker_count")}
+                {I18NextService.i18n.t("federation_worker_count")}
               </label>
               <div className="col-12">
                 <input
@@ -579,7 +591,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
                 className="form-check-label"
                 htmlFor="create-site-captcha-enabled"
               >
-                {i18n.t("captcha_enabled")}
+                {I18NextService.i18n.t("captcha_enabled")}
               </label>
             </div>
           </div>
@@ -591,7 +603,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
                 className="form-check-label me-2"
                 htmlFor="create-site-captcha-difficulty"
               >
-                {i18n.t("captcha_difficulty")}
+                {I18NextService.i18n.t("captcha_difficulty")}
               </label>
               <select
                 id="create-site-captcha-difficulty"
@@ -599,9 +611,11 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
                 onChange={linkEvent(this, this.handleSiteCaptchaDifficulty)}
                 className="form-select d-inline-block w-auto"
               >
-                <option value="easy">{i18n.t("easy")}</option>
-                <option value="medium">{i18n.t("medium")}</option>
-                <option value="hard">{i18n.t("hard")}</option>
+                <option value="easy">{I18NextService.i18n.t("easy")}</option>
+                <option value="medium">
+                  {I18NextService.i18n.t("medium")}
+                </option>
+                <option value="hard">{I18NextService.i18n.t("hard")}</option>
               </select>
             </div>
           </div>
@@ -616,9 +630,9 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
               {this.props.loading ? (
                 <Spinner />
               ) : siteSetup ? (
-                capitalizeFirstLetter(i18n.t("save"))
+                capitalizeFirstLetter(I18NextService.i18n.t("save"))
               ) : (
-                capitalizeFirstLetter(i18n.t("create"))
+                capitalizeFirstLetter(I18NextService.i18n.t("create"))
               )}
             </button>
           </div>
@@ -634,7 +648,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
     return (
       <div className="col-12 col-md-6">
         <label className="col-form-label" htmlFor={id}>
-          {i18n.t(key)}
+          {I18NextService.i18n.t(key)}
         </label>
         <div className="d-flex justify-content-between align-items-center">
           <input
index 639e1022b96f46d1863eb4b232393a98d5b03bb7..78090dd9e40661c094ecf8074e81cd178011558d 100644 (file)
@@ -1,7 +1,7 @@
 import { Component, linkEvent } from "inferno";
 import { PersonView, Site, SiteAggregates } from "lemmy-js-client";
-import { i18n } from "../../i18next";
 import { mdToHtml } from "../../markdown";
+import { I18NextService } from "../../services";
 import { Badges } from "../common/badges";
 import { BannerIconHeader } from "../common/banner-icon-header";
 import { Icon } from "../common/icon";
@@ -62,10 +62,14 @@ export class SiteSidebar extends Component<SiteSidebarProps, SiteSidebarState> {
             className="btn btn-sm"
             onClick={linkEvent(this, this.handleCollapseSidebar)}
             aria-label={
-              this.state.collapsed ? i18n.t("expand") : i18n.t("collapse")
+              this.state.collapsed
+                ? I18NextService.i18n.t("expand")
+                : I18NextService.i18n.t("collapse")
             }
             data-tippy-content={
-              this.state.collapsed ? i18n.t("expand") : i18n.t("collapse")
+              this.state.collapsed
+                ? I18NextService.i18n.t("expand")
+                : I18NextService.i18n.t("collapse")
             }
             data-bs-toggle="collapse"
             data-bs-target="#sidebarInfoBody"
@@ -104,7 +108,7 @@ export class SiteSidebar extends Component<SiteSidebarProps, SiteSidebarState> {
   admins(admins: PersonView[]) {
     return (
       <ul className="mt-1 list-inline small mb-0">
-        <li className="list-inline-item">{i18n.t("admins")}:</li>
+        <li className="list-inline-item">{I18NextService.i18n.t("admins")}:</li>
         {admins.map(av => (
           <li key={av.person.id} className="list-inline-item">
             <PersonListing person={av.person} />
index 60986c55dba43e0c80022dccc71a6678ce7f84c6..c79d9554b0c415292534ff2893c758e8c6101e7f 100644 (file)
@@ -2,7 +2,7 @@ import { myAuthRequired } from "@utils/app";
 import { capitalizeFirstLetter } from "@utils/helpers";
 import { Component, InfernoMouseEvent, linkEvent } from "inferno";
 import { EditSite, Tagline } from "lemmy-js-client";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 import { HtmlTags } from "../common/html-tags";
 import { Icon, Spinner } from "../common/icon";
 import { MarkdownTextArea } from "../common/markdown-textarea";
@@ -27,7 +27,7 @@ export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
     super(props, context);
   }
   get documentTitle(): string {
-    return i18n.t("taglines");
+    return I18NextService.i18n.t("taglines");
   }
 
   render() {
@@ -37,7 +37,7 @@ export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
           title={this.documentTitle}
           path={this.context.router.route.match.url}
         />
-        <h5 className="col-12">{i18n.t("taglines")}</h5>
+        <h5 className="col-12">{I18NextService.i18n.t("taglines")}</h5>
         <div className="table-responsive col-12">
           <table id="taglines_table" className="table table-sm table-hover">
             <thead className="pointer">
@@ -68,8 +68,8 @@ export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
                         { i: this, index: index },
                         this.handleEditTaglineClick
                       )}
-                      data-tippy-content={i18n.t("edit")}
-                      aria-label={i18n.t("edit")}
+                      data-tippy-content={I18NextService.i18n.t("edit")}
+                      aria-label={I18NextService.i18n.t("edit")}
                     >
                       <Icon icon="edit" classes={`icon-inline`} />
                     </button>
@@ -80,8 +80,8 @@ export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
                         { i: this, index: index },
                         this.handleDeleteTaglineClick
                       )}
-                      data-tippy-content={i18n.t("delete")}
-                      aria-label={i18n.t("delete")}
+                      data-tippy-content={I18NextService.i18n.t("delete")}
+                      aria-label={I18NextService.i18n.t("delete")}
                     >
                       <Icon icon="trash" classes={`icon-inline text-danger`} />
                     </button>
@@ -96,7 +96,7 @@ export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
                 className="btn btn-sm btn-secondary me-2"
                 onClick={linkEvent(this, this.handleAddTaglineClick)}
               >
-                {i18n.t("add_tagline")}
+                {I18NextService.i18n.t("add_tagline")}
               </button>
             </div>
           </div>
@@ -111,7 +111,7 @@ export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
                 {this.props.loading ? (
                   <Spinner />
                 ) : (
-                  capitalizeFirstLetter(i18n.t("save"))
+                  capitalizeFirstLetter(I18NextService.i18n.t("save"))
                 )}
               </button>
             </div>
index edced0f4b484b2be1e9fe72b5889a5bced8ebeca..e705bac86694affe85e7f72d7dbe71ece7b0e841 100644 (file)
@@ -46,9 +46,8 @@ import {
 } from "lemmy-js-client";
 import moment from "moment";
 import { fetchLimit } from "../config";
-import { i18n } from "../i18next";
 import { InitialFetchRequest } from "../interfaces";
-import { FirstLoadService } from "../services/FirstLoadService";
+import { FirstLoadService, I18NextService } from "../services";
 import { HttpService, RequestState } from "../services/HttpService";
 import { HtmlTags } from "./common/html-tags";
 import { Icon, Spinner } from "./common/icon";
@@ -586,14 +585,14 @@ const Filter = ({
 }) => (
   <div className="col-sm-6 mb-3">
     <label className="mb-2" htmlFor={`filter-${filterType}`}>
-      {i18n.t(`filter_by_${filterType}` as NoOptionI18nKeys)}
+      {I18NextService.i18n.t(`filter_by_${filterType}` as NoOptionI18nKeys)}
     </label>
     <SearchableSelect
       id={`filter-${filterType}`}
       value={value ?? 0}
       options={[
         {
-          label: i18n.t("all"),
+          label: I18NextService.i18n.t("all"),
           value: "0",
         },
       ].concat(options)}
@@ -724,8 +723,8 @@ export class Modlog extends Component<
       this.isoData.site_res.admins.some(
         ({ person: { id } }) => id === person.id
       )
-      ? i18n.t("admin")
-      : i18n.t("mod");
+      ? I18NextService.i18n.t("admin")
+      : I18NextService.i18n.t("mod");
   }
 
   get documentTitle(): string {
@@ -770,7 +769,7 @@ export class Modlog extends Component<
               >
                 /c/{this.state.communityRes.data.community_view.community.name}{" "}
               </Link>
-              <span>{i18n.t("modlog")}</span>
+              <span>{I18NextService.i18n.t("modlog")}</span>
             </h5>
           )}
           <div className="row mb-2">
@@ -782,9 +781,9 @@ export class Modlog extends Component<
                 aria-label="action"
               >
                 <option disabled aria-hidden="true">
-                  {i18n.t("filter_by_action")}
+                  {I18NextService.i18n.t("filter_by_action")}
                 </option>
-                <option value={"All"}>{i18n.t("all")}</option>
+                <option value={"All"}>{I18NextService.i18n.t("all")}</option>
                 <option value={"ModRemovePost"}>Removing Posts</option>
                 <option value={"ModLockPost"}>Locking Posts</option>
                 <option value={"ModFeaturePost"}>Featuring Posts</option>
@@ -848,9 +847,9 @@ export class Modlog extends Component<
             <table id="modlog_table" className="table table-sm table-hover">
               <thead className="pointer">
                 <tr>
-                  <th> {i18n.t("time")}</th>
-                  <th>{i18n.t("mod")}</th>
-                  <th>{i18n.t("action")}</th>
+                  <th> {I18NextService.i18n.t("time")}</th>
+                  <th>{I18NextService.i18n.t("mod")}</th>
+                  <th>{I18NextService.i18n.t("action")}</th>
                 </tr>
               </thead>
               {this.combined}
index d083f26fe352d9160a8acebde800ccc7383d17e7..ddb12beaa86f458516f7914bc40edc9ebab3d7db 100644 (file)
@@ -1,5 +1,5 @@
 import { Component } from "inferno";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 import { Icon } from "../common/icon";
 
 interface CakeDayProps {
@@ -19,6 +19,8 @@ export class CakeDay extends Component<CakeDayProps, any> {
   }
 
   cakeDayTippy(): string {
-    return i18n.t("cake_day_info", { creator_name: this.props.creatorName });
+    return I18NextService.i18n.t("cake_day_info", {
+      creator_name: this.props.creatorName,
+    });
   }
 }
index 91bbee03eea14a241285b8eb69338552bc63a65c..062fc01c5e7bdb70b17a16f613b9ac498f646d2d 100644 (file)
@@ -59,10 +59,8 @@ import {
   TransferCommunity,
 } from "lemmy-js-client";
 import { fetchLimit, relTags } from "../../config";
-import { i18n } from "../../i18next";
 import { CommentViewType, InitialFetchRequest } from "../../interfaces";
-import { UserService } from "../../services";
-import { FirstLoadService } from "../../services/FirstLoadService";
+import { FirstLoadService, I18NextService, UserService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
 import { toast } from "../../toast";
 import { CommentNodes } from "../comment/comment-nodes";
@@ -187,9 +185,9 @@ export class Inbox extends Component<any, InboxState> {
   get documentTitle(): string {
     const mui = UserService.Instance.myUserInfo;
     return mui
-      ? `@${mui.local_user_view.person.name} ${i18n.t("inbox")} - ${
-          this.state.siteRes.site_view.site.name
-        }`
+      ? `@${mui.local_user_view.person.name} ${I18NextService.i18n.t(
+          "inbox"
+        )} - ${this.state.siteRes.site_view.site.name}`
       : "";
   }
 
@@ -223,7 +221,7 @@ export class Inbox extends Component<any, InboxState> {
               path={this.context.router.route.match.url}
             />
             <h5 className="mb-2">
-              {i18n.t("inbox")}
+              {I18NextService.i18n.t("inbox")}
               {inboxRss && (
                 <small>
                   <a href={inboxRss} title="RSS" rel={relTags}>
@@ -245,7 +243,7 @@ export class Inbox extends Component<any, InboxState> {
                 {this.state.markAllAsReadRes.state == "loading" ? (
                   <Spinner />
                 ) : (
-                  i18n.t("mark_all_as_read")
+                  I18NextService.i18n.t("mark_all_as_read")
                 )}
               </button>
             )}
@@ -296,7 +294,7 @@ export class Inbox extends Component<any, InboxState> {
             checked={this.state.unreadOrAll == UnreadOrAll.Unread}
             onChange={linkEvent(this, this.handleUnreadOrAllChange)}
           />
-          {i18n.t("unread")}
+          {I18NextService.i18n.t("unread")}
         </label>
         <label
           className={`btn btn-outline-secondary pointer
@@ -310,7 +308,7 @@ export class Inbox extends Component<any, InboxState> {
             checked={this.state.unreadOrAll == UnreadOrAll.All}
             onChange={linkEvent(this, this.handleUnreadOrAllChange)}
           />
-          {i18n.t("all")}
+          {I18NextService.i18n.t("all")}
         </label>
       </div>
     );
@@ -331,7 +329,7 @@ export class Inbox extends Component<any, InboxState> {
             checked={this.state.messageType == MessageType.All}
             onChange={linkEvent(this, this.handleMessageTypeChange)}
           />
-          {i18n.t("all")}
+          {I18NextService.i18n.t("all")}
         </label>
         <label
           className={`btn btn-outline-secondary pointer
@@ -345,7 +343,7 @@ export class Inbox extends Component<any, InboxState> {
             checked={this.state.messageType == MessageType.Replies}
             onChange={linkEvent(this, this.handleMessageTypeChange)}
           />
-          {i18n.t("replies")}
+          {I18NextService.i18n.t("replies")}
         </label>
         <label
           className={`btn btn-outline-secondary pointer
@@ -359,7 +357,7 @@ export class Inbox extends Component<any, InboxState> {
             checked={this.state.messageType == MessageType.Mentions}
             onChange={linkEvent(this, this.handleMessageTypeChange)}
           />
-          {i18n.t("mentions")}
+          {I18NextService.i18n.t("mentions")}
         </label>
         <label
           className={`btn btn-outline-secondary pointer
@@ -373,7 +371,7 @@ export class Inbox extends Component<any, InboxState> {
             checked={this.state.messageType == MessageType.Messages}
             onChange={linkEvent(this, this.handleMessageTypeChange)}
           />
-          {i18n.t("messages")}
+          {I18NextService.i18n.t("messages")}
         </label>
       </div>
     );
@@ -826,7 +824,7 @@ export class Inbox extends Component<any, InboxState> {
     const res = await HttpService.client.createComment(form);
 
     if (res.state === "success") {
-      toast(i18n.t("reply_sent"));
+      toast(I18NextService.i18n.t("reply_sent"));
       this.findAndUpdateComment(res);
     }
 
@@ -837,7 +835,7 @@ export class Inbox extends Component<any, InboxState> {
     const res = await HttpService.client.editComment(form);
 
     if (res.state === "success") {
-      toast(i18n.t("edit"));
+      toast(I18NextService.i18n.t("edit"));
       this.findAndUpdateComment(res);
     } else if (res.state === "failed") {
       toast(res.msg, "danger");
@@ -849,7 +847,7 @@ export class Inbox extends Component<any, InboxState> {
   async handleDeleteComment(form: DeleteComment) {
     const res = await HttpService.client.deleteComment(form);
     if (res.state == "success") {
-      toast(i18n.t("deleted"));
+      toast(I18NextService.i18n.t("deleted"));
       this.findAndUpdateComment(res);
     }
   }
@@ -857,7 +855,7 @@ export class Inbox extends Component<any, InboxState> {
   async handleRemoveComment(form: RemoveComment) {
     const res = await HttpService.client.removeComment(form);
     if (res.state == "success") {
-      toast(i18n.t("remove_comment"));
+      toast(I18NextService.i18n.t("remove_comment"));
       this.findAndUpdateComment(res);
     }
   }
@@ -892,7 +890,7 @@ export class Inbox extends Component<any, InboxState> {
 
   async handleTransferCommunity(form: TransferCommunity) {
     await HttpService.client.transferCommunity(form);
-    toast(i18n.t("transfer_community"));
+    toast(I18NextService.i18n.t("transfer_community"));
   }
 
   async handleCommentReplyRead(form: MarkCommentReplyAsRead) {
@@ -1004,7 +1002,7 @@ export class Inbox extends Component<any, InboxState> {
 
   purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
     if (purgeRes.state == "success") {
-      toast(i18n.t("purge_success"));
+      toast(I18NextService.i18n.t("purge_success"));
       this.context.router.history.push(`/`);
     }
   }
@@ -1013,7 +1011,7 @@ export class Inbox extends Component<any, InboxState> {
     res: RequestState<PrivateMessageReportResponse | CommentReportResponse>
   ) {
     if (res.state == "success") {
-      toast(i18n.t("report_created"));
+      toast(I18NextService.i18n.t("report_created"));
     }
   }
 
index e20c31382d2fa1f469f2ab5cb419652ca39df809..dd85e05b3a1961e9f91975ac74185f8db8489291 100644 (file)
@@ -2,8 +2,7 @@ import { myAuth, setIsoData } from "@utils/app";
 import { capitalizeFirstLetter } from "@utils/helpers";
 import { Component, linkEvent } from "inferno";
 import { GetSiteResponse, LoginResponse } from "lemmy-js-client";
-import { i18n } from "../../i18next";
-import { HttpService, UserService } from "../../services";
+import { HttpService, I18NextService, UserService } from "../../services";
 import { RequestState } from "../../services/HttpService";
 import { HtmlTags } from "../common/html-tags";
 import { Spinner } from "../common/icon";
@@ -34,7 +33,7 @@ export class PasswordChange extends Component<any, State> {
   }
 
   get documentTitle(): string {
-    return `${i18n.t("password_change")} - ${
+    return `${I18NextService.i18n.t("password_change")} - ${
       this.state.siteRes.site_view.site.name
     }`;
   }
@@ -48,7 +47,7 @@ export class PasswordChange extends Component<any, State> {
         />
         <div className="row">
           <div className="col-12 col-lg-6 offset-lg-3 mb-4">
-            <h5>{i18n.t("password_change")}</h5>
+            <h5>{I18NextService.i18n.t("password_change")}</h5>
             {this.passwordChangeForm()}
           </div>
         </div>
@@ -61,7 +60,7 @@ export class PasswordChange extends Component<any, State> {
       <form onSubmit={linkEvent(this, this.handlePasswordChangeSubmit)}>
         <div className="mb-3 row">
           <label className="col-sm-2 col-form-label" htmlFor="new-password">
-            {i18n.t("new_password")}
+            {I18NextService.i18n.t("new_password")}
           </label>
           <div className="col-sm-10">
             <input
@@ -77,7 +76,7 @@ export class PasswordChange extends Component<any, State> {
         </div>
         <div className="mb-3 row">
           <label className="col-sm-2 col-form-label" htmlFor="verify-password">
-            {i18n.t("verify_password")}
+            {I18NextService.i18n.t("verify_password")}
           </label>
           <div className="col-sm-10">
             <input
@@ -97,7 +96,7 @@ export class PasswordChange extends Component<any, State> {
               {this.state.passwordChangeRes.state == "loading" ? (
                 <Spinner />
               ) : (
-                capitalizeFirstLetter(i18n.t("save"))
+                capitalizeFirstLetter(I18NextService.i18n.t("save"))
               )}
             </button>
           </div>
index 763947e8e1b07f50e1fe78d158c34876588fe9b1..d00036871a04c9ec922c93a56e5c9b6eb43fec8b 100644 (file)
@@ -72,11 +72,9 @@ import {
 } from "lemmy-js-client";
 import moment from "moment";
 import { fetchLimit, relTags } from "../../config";
-import { i18n } from "../../i18next";
 import { InitialFetchRequest, PersonDetailsView } from "../../interfaces";
 import { mdToHtml } from "../../markdown";
-import { UserService } from "../../services";
-import { FirstLoadService } from "../../services/FirstLoadService";
+import { FirstLoadService, I18NextService, UserService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
 import { setupTippy } from "../../tippy";
 import { toast } from "../../toast";
@@ -137,7 +135,7 @@ const getCommunitiesListing = (
   communityViews.length > 0 && (
     <div className="card border-secondary mb-3">
       <div className="card-body">
-        <h5>{i18n.t(translationKey)}</h5>
+        <h5>{I18NextService.i18n.t(translationKey)}</h5>
         <ul className="list-unstyled mb-0">
           {communityViews.map(({ community }) => (
             <li key={community.id}>
@@ -422,7 +420,7 @@ export class Profile extends Component<
           checked={active}
           onChange={linkEvent(this, this.handleViewChange)}
         />
-        {i18n.t(view.toLowerCase() as NoOptionI18nKeys)}
+        {I18NextService.i18n.t(view.toLowerCase() as NoOptionI18nKeys)}
       </label>
     );
   }
@@ -485,22 +483,22 @@ export class Profile extends Component<
                     </li>
                     {isBanned(pv.person) && (
                       <li className="list-inline-item badge text-bg-danger">
-                        {i18n.t("banned")}
+                        {I18NextService.i18n.t("banned")}
                       </li>
                     )}
                     {pv.person.deleted && (
                       <li className="list-inline-item badge text-bg-danger">
-                        {i18n.t("deleted")}
+                        {I18NextService.i18n.t("deleted")}
                       </li>
                     )}
                     {pv.person.admin && (
                       <li className="list-inline-item badge text-bg-light">
-                        {i18n.t("admin")}
+                        {I18NextService.i18n.t("admin")}
                       </li>
                     )}
                     {pv.person.bot_account && (
                       <li className="list-inline-item badge text-bg-light">
-                        {i18n.t("bot_account").toLowerCase()}
+                        {I18NextService.i18n.t("bot_account").toLowerCase()}
                       </li>
                     )}
                   </ul>
@@ -516,7 +514,7 @@ export class Profile extends Component<
                       rel={relTags}
                       href={`https://matrix.to/#/${pv.person.matrix_user_id}`}
                     >
-                      {i18n.t("send_secure_message")}
+                      {I18NextService.i18n.t("send_secure_message")}
                     </a>
                     <Link
                       className={
@@ -524,7 +522,7 @@ export class Profile extends Component<
                       }
                       to={`/create_private_message/${pv.person.id}`}
                     >
-                      {i18n.t("send_message")}
+                      {I18NextService.i18n.t("send_message")}
                     </Link>
                     {personBlocked ? (
                       <button
@@ -536,7 +534,7 @@ export class Profile extends Component<
                           this.handleUnblockPerson
                         )}
                       >
-                        {i18n.t("unblock_user")}
+                        {I18NextService.i18n.t("unblock_user")}
                       </button>
                     ) : (
                       <button
@@ -548,7 +546,7 @@ export class Profile extends Component<
                           this.handleBlockPerson
                         )}
                       >
-                        {i18n.t("block_user")}
+                        {I18NextService.i18n.t("block_user")}
                       </button>
                     )}
                   </>
@@ -563,9 +561,9 @@ export class Profile extends Component<
                         "d-flex align-self-start btn btn-secondary me-2"
                       }
                       onClick={linkEvent(this, this.handleModBanShow)}
-                      aria-label={i18n.t("ban")}
+                      aria-label={I18NextService.i18n.t("ban")}
                     >
-                      {capitalizeFirstLetter(i18n.t("ban"))}
+                      {capitalizeFirstLetter(I18NextService.i18n.t("ban"))}
                     </button>
                   ) : (
                     <button
@@ -573,9 +571,9 @@ export class Profile extends Component<
                         "d-flex align-self-start btn btn-secondary me-2"
                       }
                       onClick={linkEvent(this, this.handleModBanSubmit)}
-                      aria-label={i18n.t("unban")}
+                      aria-label={I18NextService.i18n.t("unban")}
                     >
-                      {capitalizeFirstLetter(i18n.t("unban"))}
+                      {capitalizeFirstLetter(I18NextService.i18n.t("unban"))}
                     </button>
                   ))}
               </div>
@@ -590,13 +588,13 @@ export class Profile extends Component<
               <div>
                 <ul className="list-inline mb-2">
                   <li className="list-inline-item badge text-bg-light">
-                    {i18n.t("number_of_posts", {
+                    {I18NextService.i18n.t("number_of_posts", {
                       count: Number(pv.counts.post_count),
                       formattedCount: numToSI(pv.counts.post_count),
                     })}
                   </li>
                   <li className="list-inline-item badge text-bg-light">
-                    {i18n.t("number_of_comments", {
+                    {I18NextService.i18n.t("number_of_comments", {
                       count: Number(pv.counts.comment_count),
                       formattedCount: numToSI(pv.counts.comment_count),
                     })}
@@ -604,7 +602,7 @@ export class Profile extends Component<
                 </ul>
               </div>
               <div className="text-muted">
-                {i18n.t("joined")}{" "}
+                {I18NextService.i18n.t("joined")}{" "}
                 <MomentTime
                   published={pv.person.published}
                   showAgo
@@ -614,7 +612,7 @@ export class Profile extends Component<
               <div className="d-flex align-items-center text-muted mb-2">
                 <Icon icon="cake" />
                 <span className="ms-2">
-                  {i18n.t("cake_day_title")}{" "}
+                  {I18NextService.i18n.t("cake_day_title")}{" "}
                   {moment
                     .utc(pv.person.published)
                     .local()
@@ -623,7 +621,7 @@ export class Profile extends Component<
               </div>
               {!UserService.Instance.myUserInfo && (
                 <div className="alert alert-info" role="alert">
-                  {i18n.t("profile_not_logged_in_alert")}
+                  {I18NextService.i18n.t("profile_not_logged_in_alert")}
                 </div>
               )}
             </div>
@@ -641,24 +639,24 @@ export class Profile extends Component<
         <form onSubmit={linkEvent(this, this.handleModBanSubmit)}>
           <div className="mb-3 row col-12">
             <label className="col-form-label" htmlFor="profile-ban-reason">
-              {i18n.t("reason")}
+              {I18NextService.i18n.t("reason")}
             </label>
             <input
               type="text"
               id="profile-ban-reason"
               className="form-control me-2"
-              placeholder={i18n.t("reason")}
+              placeholder={I18NextService.i18n.t("reason")}
               value={this.state.banReason}
               onInput={linkEvent(this, this.handleModBanReasonChange)}
             />
             <label className="col-form-label" htmlFor={`mod-ban-expires`}>
-              {i18n.t("expires")}
+              {I18NextService.i18n.t("expires")}
             </label>
             <input
               type="number"
               id={`mod-ban-expires`}
               className="form-control me-2"
-              placeholder={i18n.t("number_of_days")}
+              placeholder={I18NextService.i18n.t("number_of_days")}
               value={this.state.banExpireDays}
               onInput={linkEvent(this, this.handleModBanExpireDaysChange)}
             />
@@ -674,9 +672,9 @@ export class Profile extends Component<
                 <label
                   className="form-check-label"
                   htmlFor="mod-ban-remove-data"
-                  title={i18n.t("remove_content_more")}
+                  title={I18NextService.i18n.t("remove_content_more")}
                 >
-                  {i18n.t("remove_content")}
+                  {I18NextService.i18n.t("remove_content")}
                 </label>
               </div>
             </div>
@@ -684,23 +682,23 @@ export class Profile extends Component<
           {/* TODO hold off on expires until later */}
           {/* <div class="mb-3 row"> */}
           {/*   <label class="col-form-label">Expires</label> */}
-          {/*   <input type="date" class="form-control me-2" placeholder={i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
+          {/*   <input type="date" class="form-control me-2" placeholder={I18NextService.i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
           {/* </div> */}
           <div className="mb-3 row">
             <button
               type="reset"
               className="btn btn-secondary me-2"
-              aria-label={i18n.t("cancel")}
+              aria-label={I18NextService.i18n.t("cancel")}
               onClick={linkEvent(this, this.handleModBanSubmitCancel)}
             >
-              {i18n.t("cancel")}
+              {I18NextService.i18n.t("cancel")}
             </button>
             <button
               type="submit"
               className="btn btn-secondary"
-              aria-label={i18n.t("ban")}
+              aria-label={I18NextService.i18n.t("ban")}
             >
-              {i18n.t("ban")} {pv.person.name}
+              {I18NextService.i18n.t("ban")} {pv.person.name}
             </button>
           </div>
         </form>
@@ -904,14 +902,14 @@ export class Profile extends Component<
   async handleCommentReport(form: CreateCommentReport) {
     const reportRes = await HttpService.client.createCommentReport(form);
     if (reportRes.state === "success") {
-      toast(i18n.t("report_created"));
+      toast(I18NextService.i18n.t("report_created"));
     }
   }
 
   async handlePostReport(form: CreatePostReport) {
     const reportRes = await HttpService.client.createPostReport(form);
     if (reportRes.state === "success") {
-      toast(i18n.t("report_created"));
+      toast(I18NextService.i18n.t("report_created"));
     }
   }
 
@@ -935,7 +933,7 @@ export class Profile extends Component<
 
   async handleTransferCommunity(form: TransferCommunity) {
     await HttpService.client.transferCommunity(form);
-    toast(i18n.t("transfer_community"));
+    toast(I18NextService.i18n.t("transfer_community"));
   }
 
   async handleCommentReplyRead(form: MarkCommentReplyAsRead) {
@@ -999,7 +997,7 @@ export class Profile extends Component<
 
   purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
     if (purgeRes.state == "success") {
-      toast(i18n.t("purge_success"));
+      toast(I18NextService.i18n.t("purge_success"));
       this.context.router.history.push(`/`);
     }
   }
index 0e636fc77352a95afc6765a9ba4df99c3dd610b6..d9eb6ad0a65ed1d9f858f90a688c377f47e51685 100644 (file)
@@ -12,10 +12,8 @@ import {
   RegistrationApplicationView,
 } from "lemmy-js-client";
 import { fetchLimit } from "../../config";
-import { i18n } from "../../i18next";
 import { InitialFetchRequest } from "../../interfaces";
-import { UserService } from "../../services";
-import { FirstLoadService } from "../../services/FirstLoadService";
+import { FirstLoadService, I18NextService, UserService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
 import { setupTippy } from "../../tippy";
 import { HtmlTags } from "../common/html-tags";
@@ -79,7 +77,7 @@ export class RegistrationApplications extends Component<
   get documentTitle(): string {
     const mui = UserService.Instance.myUserInfo;
     return mui
-      ? `@${mui.local_user_view.person.name} ${i18n.t(
+      ? `@${mui.local_user_view.person.name} ${I18NextService.i18n.t(
           "registration_applications"
         )} - ${this.state.siteRes.site_view.site.name}`
       : "";
@@ -102,7 +100,9 @@ export class RegistrationApplications extends Component<
                 title={this.documentTitle}
                 path={this.context.router.route.match.url}
               />
-              <h5 className="mb-2">{i18n.t("registration_applications")}</h5>
+              <h5 className="mb-2">
+                {I18NextService.i18n.t("registration_applications")}
+              </h5>
               {this.selects()}
               {this.applicationList(apps)}
               <Paginator
@@ -139,7 +139,7 @@ export class RegistrationApplications extends Component<
             checked={this.state.unreadOrAll == UnreadOrAll.Unread}
             onChange={linkEvent(this, this.handleUnreadOrAllChange)}
           />
-          {i18n.t("unread")}
+          {I18NextService.i18n.t("unread")}
         </label>
         <label
           className={`btn btn-outline-secondary pointer
@@ -153,7 +153,7 @@ export class RegistrationApplications extends Component<
             checked={this.state.unreadOrAll == UnreadOrAll.All}
             onChange={linkEvent(this, this.handleUnreadOrAllChange)}
           />
-          {i18n.t("all")}
+          {I18NextService.i18n.t("all")}
         </label>
       </div>
     );
index 6fe59f1c4bafb2a74835e4168ad8a0d7e0bb6f0d..8f5eaf366b6dcf0d99022ae2d8a13d455b85762e 100644 (file)
@@ -27,10 +27,13 @@ import {
   ResolvePrivateMessageReport,
 } from "lemmy-js-client";
 import { fetchLimit } from "../../config";
-import { i18n } from "../../i18next";
 import { InitialFetchRequest } from "../../interfaces";
-import { HttpService, UserService } from "../../services";
-import { FirstLoadService } from "../../services/FirstLoadService";
+import {
+  FirstLoadService,
+  HttpService,
+  I18NextService,
+  UserService,
+} from "../../services";
 import { RequestState } from "../../services/HttpService";
 import { CommentReport } from "../comment/comment-report";
 import { HtmlTags } from "../common/html-tags";
@@ -134,9 +137,9 @@ export class Reports extends Component<any, ReportsState> {
   get documentTitle(): string {
     const mui = UserService.Instance.myUserInfo;
     return mui
-      ? `@${mui.local_user_view.person.name} ${i18n.t("reports")} - ${
-          this.state.siteRes.site_view.site.name
-        }`
+      ? `@${mui.local_user_view.person.name} ${I18NextService.i18n.t(
+          "reports"
+        )} - ${this.state.siteRes.site_view.site.name}`
       : "";
   }
 
@@ -149,7 +152,7 @@ export class Reports extends Component<any, ReportsState> {
               title={this.documentTitle}
               path={this.context.router.route.match.url}
             />
-            <h5 className="mb-2">{i18n.t("reports")}</h5>
+            <h5 className="mb-2">{I18NextService.i18n.t("reports")}</h5>
             {this.selects()}
             {this.section}
             <Paginator
@@ -198,7 +201,7 @@ export class Reports extends Component<any, ReportsState> {
             checked={this.state.unreadOrAll == UnreadOrAll.Unread}
             onChange={linkEvent(this, this.handleUnreadOrAllChange)}
           />
-          {i18n.t("unread")}
+          {I18NextService.i18n.t("unread")}
         </label>
         <label
           className={`btn btn-outline-secondary pointer
@@ -212,7 +215,7 @@ export class Reports extends Component<any, ReportsState> {
             checked={this.state.unreadOrAll == UnreadOrAll.All}
             onChange={linkEvent(this, this.handleUnreadOrAllChange)}
           />
-          {i18n.t("all")}
+          {I18NextService.i18n.t("all")}
         </label>
       </div>
     );
@@ -233,7 +236,7 @@ export class Reports extends Component<any, ReportsState> {
             checked={this.state.messageType == MessageType.All}
             onChange={linkEvent(this, this.handleMessageTypeChange)}
           />
-          {i18n.t("all")}
+          {I18NextService.i18n.t("all")}
         </label>
         <label
           className={`btn btn-outline-secondary pointer
@@ -247,7 +250,7 @@ export class Reports extends Component<any, ReportsState> {
             checked={this.state.messageType == MessageType.CommentReport}
             onChange={linkEvent(this, this.handleMessageTypeChange)}
           />
-          {i18n.t("comments")}
+          {I18NextService.i18n.t("comments")}
         </label>
         <label
           className={`btn btn-outline-secondary pointer
@@ -261,7 +264,7 @@ export class Reports extends Component<any, ReportsState> {
             checked={this.state.messageType == MessageType.PostReport}
             onChange={linkEvent(this, this.handleMessageTypeChange)}
           />
-          {i18n.t("posts")}
+          {I18NextService.i18n.t("posts")}
         </label>
         {amAdmin() && (
           <label
@@ -281,7 +284,7 @@ export class Reports extends Component<any, ReportsState> {
               }
               onChange={linkEvent(this, this.handleMessageTypeChange)}
             />
-            {i18n.t("messages")}
+            {I18NextService.i18n.t("messages")}
           </label>
         )}
       </div>
index 5f149dfe2960b569f17262c9874cd3a9819175db..dc542e72594518b49c5efd3f39c8be1431ea1722 100644 (file)
@@ -29,9 +29,9 @@ import {
   SortType,
 } from "lemmy-js-client";
 import { elementUrl, emDash, relTags } from "../../config";
-import { i18n, languages } from "../../i18next";
 import { UserService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
+import { I18NextService, languages } from "../../services/I18NextService";
 import { setupTippy } from "../../tippy";
 import { toast } from "../../toast";
 import { HtmlTags } from "../common/html-tags";
@@ -113,7 +113,7 @@ const Filter = ({
       className="col-md-4 col-form-label"
       htmlFor={`block-${filterType}-filter`}
     >
-      {i18n.t(`block_${filterType}` as NoOptionI18nKeys)}
+      {I18NextService.i18n.t(`block_${filterType}` as NoOptionI18nKeys)}
     </label>
     <div className="col-md-8">
       <SearchableSelect
@@ -233,7 +233,7 @@ export class Settings extends Component<any, SettingsState> {
   }
 
   get documentTitle(): string {
-    return i18n.t("settings");
+    return I18NextService.i18n.t("settings");
   }
 
   render() {
@@ -249,12 +249,12 @@ export class Settings extends Component<any, SettingsState> {
           tabs={[
             {
               key: "settings",
-              label: i18n.t("settings"),
+              label: I18NextService.i18n.t("settings"),
               getNode: this.userSettings,
             },
             {
               key: "blocks",
-              label: i18n.t("blocks"),
+              label: I18NextService.i18n.t("blocks"),
               getNode: this.blockCards,
             },
           ]}
@@ -316,11 +316,11 @@ export class Settings extends Component<any, SettingsState> {
   changePasswordHtmlForm() {
     return (
       <>
-        <h5>{i18n.t("change_password")}</h5>
+        <h5>{I18NextService.i18n.t("change_password")}</h5>
         <form onSubmit={linkEvent(this, this.handleChangePasswordSubmit)}>
           <div className="mb-3 row">
             <label className="col-sm-5 col-form-label" htmlFor="user-password">
-              {i18n.t("new_password")}
+              {I18NextService.i18n.t("new_password")}
             </label>
             <div className="col-sm-7">
               <input
@@ -339,7 +339,7 @@ export class Settings extends Component<any, SettingsState> {
               className="col-sm-5 col-form-label"
               htmlFor="user-verify-password"
             >
-              {i18n.t("verify_password")}
+              {I18NextService.i18n.t("verify_password")}
             </label>
             <div className="col-sm-7">
               <input
@@ -358,7 +358,7 @@ export class Settings extends Component<any, SettingsState> {
               className="col-sm-5 col-form-label"
               htmlFor="user-old-password"
             >
-              {i18n.t("old_password")}
+              {I18NextService.i18n.t("old_password")}
             </label>
             <div className="col-sm-7">
               <input
@@ -380,7 +380,7 @@ export class Settings extends Component<any, SettingsState> {
               {this.state.changePasswordRes.state === "loading" ? (
                 <Spinner />
               ) : (
-                capitalizeFirstLetter(i18n.t("save"))
+                capitalizeFirstLetter(I18NextService.i18n.t("save"))
               )}
             </button>
           </div>
@@ -409,7 +409,7 @@ export class Settings extends Component<any, SettingsState> {
   blockedUsersList() {
     return (
       <>
-        <h5>{i18n.t("blocked_users")}</h5>
+        <h5>{I18NextService.i18n.t("blocked_users")}</h5>
         <ul className="list-unstyled mb-0">
           {this.state.personBlocks.map(pb => (
             <li key={pb.target.id}>
@@ -421,7 +421,7 @@ export class Settings extends Component<any, SettingsState> {
                     { ctx: this, recipientId: pb.target.id },
                     this.handleUnblockPerson
                   )}
-                  data-tippy-content={i18n.t("unblock_user")}
+                  data-tippy-content={I18NextService.i18n.t("unblock_user")}
                 >
                   <Icon icon="x" classes="icon-inline" />
                 </button>
@@ -453,7 +453,7 @@ export class Settings extends Component<any, SettingsState> {
   blockedCommunitiesList() {
     return (
       <>
-        <h5>{i18n.t("blocked_communities")}</h5>
+        <h5>{I18NextService.i18n.t("blocked_communities")}</h5>
         <ul className="list-unstyled mb-0">
           {this.state.communityBlocks.map(cb => (
             <li key={cb.community.id}>
@@ -465,7 +465,9 @@ export class Settings extends Component<any, SettingsState> {
                     { ctx: this, communityId: cb.community.id },
                     this.handleUnblockCommunity
                   )}
-                  data-tippy-content={i18n.t("unblock_community")}
+                  data-tippy-content={I18NextService.i18n.t(
+                    "unblock_community"
+                  )}
                 >
                   <Icon icon="x" classes="icon-inline" />
                 </button>
@@ -482,18 +484,18 @@ export class Settings extends Component<any, SettingsState> {
 
     return (
       <>
-        <h5>{i18n.t("settings")}</h5>
+        <h5>{I18NextService.i18n.t("settings")}</h5>
         <form onSubmit={linkEvent(this, this.handleSaveSettingsSubmit)}>
           <div className="mb-3 row">
             <label className="col-sm-3 col-form-label" htmlFor="display-name">
-              {i18n.t("display_name")}
+              {I18NextService.i18n.t("display_name")}
             </label>
             <div className="col-sm-9">
               <input
                 id="display-name"
                 type="text"
                 className="form-control"
-                placeholder={i18n.t("optional")}
+                placeholder={I18NextService.i18n.t("optional")}
                 value={this.state.saveUserSettingsForm.display_name}
                 onInput={linkEvent(this, this.handleDisplayNameChange)}
                 pattern="^(?!@)(.+)$"
@@ -503,7 +505,7 @@ export class Settings extends Component<any, SettingsState> {
           </div>
           <div className="mb-3 row">
             <label className="col-sm-3 col-form-label" htmlFor="user-bio">
-              {i18n.t("bio")}
+              {I18NextService.i18n.t("bio")}
             </label>
             <div className="col-sm-9">
               <MarkdownTextArea
@@ -518,14 +520,14 @@ export class Settings extends Component<any, SettingsState> {
           </div>
           <div className="mb-3 row">
             <label className="col-sm-3 col-form-label" htmlFor="user-email">
-              {i18n.t("email")}
+              {I18NextService.i18n.t("email")}
             </label>
             <div className="col-sm-9">
               <input
                 type="email"
                 id="user-email"
                 className="form-control"
-                placeholder={i18n.t("optional")}
+                placeholder={I18NextService.i18n.t("optional")}
                 value={this.state.saveUserSettingsForm.email}
                 onInput={linkEvent(this, this.handleEmailChange)}
                 minLength={3}
@@ -535,7 +537,7 @@ export class Settings extends Component<any, SettingsState> {
           <div className="mb-3 row">
             <label className="col-sm-3 col-form-label" htmlFor="matrix-user-id">
               <a href={elementUrl} rel={relTags}>
-                {i18n.t("matrix_user_id")}
+                {I18NextService.i18n.t("matrix_user_id")}
               </a>
             </label>
             <div className="col-sm-9">
@@ -552,11 +554,11 @@ export class Settings extends Component<any, SettingsState> {
           </div>
           <div className="mb-3 row">
             <label className="col-sm-3 col-form-label">
-              {i18n.t("avatar")}
+              {I18NextService.i18n.t("avatar")}
             </label>
             <div className="col-sm-9">
               <ImageUploadForm
-                uploadTitle={i18n.t("upload_avatar")}
+                uploadTitle={I18NextService.i18n.t("upload_avatar")}
                 imageSrc={this.state.saveUserSettingsForm.avatar}
                 onUpload={this.handleAvatarUpload}
                 onRemove={this.handleAvatarRemove}
@@ -566,11 +568,11 @@ export class Settings extends Component<any, SettingsState> {
           </div>
           <div className="mb-3 row">
             <label className="col-sm-3 col-form-label">
-              {i18n.t("banner")}
+              {I18NextService.i18n.t("banner")}
             </label>
             <div className="col-sm-9">
               <ImageUploadForm
-                uploadTitle={i18n.t("upload_banner")}
+                uploadTitle={I18NextService.i18n.t("upload_banner")}
                 imageSrc={this.state.saveUserSettingsForm.banner}
                 onUpload={this.handleBannerUpload}
                 onRemove={this.handleBannerRemove}
@@ -579,7 +581,7 @@ export class Settings extends Component<any, SettingsState> {
           </div>
           <div className="mb-3 row">
             <label className="col-sm-3 form-label" htmlFor="user-language">
-              {i18n.t("interface_language")}
+              {I18NextService.i18n.t("interface_language")}
             </label>
             <div className="col-sm-9">
               <select
@@ -589,9 +591,11 @@ export class Settings extends Component<any, SettingsState> {
                 className="form-select d-inline-block w-auto"
               >
                 <option disabled aria-hidden="true">
-                  {i18n.t("interface_language")}
+                  {I18NextService.i18n.t("interface_language")}
+                </option>
+                <option value="browser">
+                  {I18NextService.i18n.t("browser_default")}
                 </option>
-                <option value="browser">{i18n.t("browser_default")}</option>
                 <option disabled aria-hidden="true">
                   ──
                 </option>
@@ -616,7 +620,7 @@ export class Settings extends Component<any, SettingsState> {
           />
           <div className="mb-3 row">
             <label className="col-sm-3 col-form-label" htmlFor="user-theme">
-              {i18n.t("theme")}
+              {I18NextService.i18n.t("theme")}
             </label>
             <div className="col-sm-9">
               <select
@@ -626,9 +630,11 @@ export class Settings extends Component<any, SettingsState> {
                 className="form-select d-inline-block w-auto"
               >
                 <option disabled aria-hidden="true">
-                  {i18n.t("theme")}
+                  {I18NextService.i18n.t("theme")}
+                </option>
+                <option value="browser">
+                  {I18NextService.i18n.t("browser_default")}
                 </option>
-                <option value="browser">{i18n.t("browser_default")}</option>
                 {this.state.themeList.map(theme => (
                   <option key={theme} value={theme}>
                     {theme}
@@ -638,7 +644,9 @@ export class Settings extends Component<any, SettingsState> {
             </div>
           </div>
           <form className="mb-3 row">
-            <label className="col-sm-3 col-form-label">{i18n.t("type")}</label>
+            <label className="col-sm-3 col-form-label">
+              {I18NextService.i18n.t("type")}
+            </label>
             <div className="col-sm-9">
               <ListingTypeSelect
                 type_={
@@ -653,7 +661,7 @@ export class Settings extends Component<any, SettingsState> {
           </form>
           <form className="mb-3 row">
             <label className="col-sm-3 col-form-label">
-              {i18n.t("sort_type")}
+              {I18NextService.i18n.t("sort_type")}
             </label>
             <div className="col-sm-9">
               <SortSelect
@@ -674,7 +682,7 @@ export class Settings extends Component<any, SettingsState> {
                 onChange={linkEvent(this, this.handleShowNsfwChange)}
               />
               <label className="form-check-label" htmlFor="user-show-nsfw">
-                {i18n.t("show_nsfw")}
+                {I18NextService.i18n.t("show_nsfw")}
               </label>
             </div>
           </div>
@@ -688,7 +696,7 @@ export class Settings extends Component<any, SettingsState> {
                 onChange={linkEvent(this, this.handleShowScoresChange)}
               />
               <label className="form-check-label" htmlFor="user-show-scores">
-                {i18n.t("show_scores")}
+                {I18NextService.i18n.t("show_scores")}
               </label>
             </div>
           </div>
@@ -702,7 +710,7 @@ export class Settings extends Component<any, SettingsState> {
                 onChange={linkEvent(this, this.handleShowAvatarsChange)}
               />
               <label className="form-check-label" htmlFor="user-show-avatars">
-                {i18n.t("show_avatars")}
+                {I18NextService.i18n.t("show_avatars")}
               </label>
             </div>
           </div>
@@ -716,7 +724,7 @@ export class Settings extends Component<any, SettingsState> {
                 onChange={linkEvent(this, this.handleBotAccount)}
               />
               <label className="form-check-label" htmlFor="user-bot-account">
-                {i18n.t("bot_account")}
+                {I18NextService.i18n.t("bot_account")}
               </label>
             </div>
           </div>
@@ -733,7 +741,7 @@ export class Settings extends Component<any, SettingsState> {
                 className="form-check-label"
                 htmlFor="user-show-bot-accounts"
               >
-                {i18n.t("show_bot_accounts")}
+                {I18NextService.i18n.t("show_bot_accounts")}
               </label>
             </div>
           </div>
@@ -750,7 +758,7 @@ export class Settings extends Component<any, SettingsState> {
                 className="form-check-label"
                 htmlFor="user-show-read-posts"
               >
-                {i18n.t("show_read_posts")}
+                {I18NextService.i18n.t("show_read_posts")}
               </label>
             </div>
           </div>
@@ -767,7 +775,7 @@ export class Settings extends Component<any, SettingsState> {
                 className="form-check-label"
                 htmlFor="user-show-new-post-notifs"
               >
-                {i18n.t("show_new_post_notifs")}
+                {I18NextService.i18n.t("show_new_post_notifs")}
               </label>
             </div>
           </div>
@@ -790,7 +798,7 @@ export class Settings extends Component<any, SettingsState> {
                 className="form-check-label"
                 htmlFor="user-send-notifications-to-email"
               >
-                {i18n.t("send_notifications_to_email")}
+                {I18NextService.i18n.t("send_notifications_to_email")}
               </label>
             </div>
           </div>
@@ -800,7 +808,7 @@ export class Settings extends Component<any, SettingsState> {
               {this.state.saveRes.state === "loading" ? (
                 <Spinner />
               ) : (
-                capitalizeFirstLetter(i18n.t("save"))
+                capitalizeFirstLetter(I18NextService.i18n.t("save"))
               )}
             </button>
           </div>
@@ -813,12 +821,12 @@ export class Settings extends Component<any, SettingsState> {
                 this.handleDeleteAccountShowConfirmToggle
               )}
             >
-              {i18n.t("delete_account")}
+              {I18NextService.i18n.t("delete_account")}
             </button>
             {this.state.deleteAccountShowConfirm && (
               <>
                 <div className="my-2 alert alert-danger" role="alert">
-                  {i18n.t("delete_account_confirm")}
+                  {I18NextService.i18n.t("delete_account_confirm")}
                 </div>
                 <input
                   type="password"
@@ -839,7 +847,7 @@ export class Settings extends Component<any, SettingsState> {
                   {this.state.deleteAccountRes.state === "loading" ? (
                     <Spinner />
                   ) : (
-                    capitalizeFirstLetter(i18n.t("delete"))
+                    capitalizeFirstLetter(I18NextService.i18n.t("delete"))
                   )}
                 </button>
                 <button
@@ -849,7 +857,7 @@ export class Settings extends Component<any, SettingsState> {
                     this.handleDeleteAccountShowConfirmToggle
                   )}
                 >
-                  {i18n.t("cancel")}
+                  {I18NextService.i18n.t("cancel")}
                 </button>
               </>
             )}
@@ -876,7 +884,7 @@ export class Settings extends Component<any, SettingsState> {
                 onChange={linkEvent(this, this.handleGenerateTotp)}
               />
               <label className="form-check-label" htmlFor="user-generate-totp">
-                {i18n.t("set_up_two_factor")}
+                {I18NextService.i18n.t("set_up_two_factor")}
               </label>
             </div>
           </div>
@@ -886,7 +894,7 @@ export class Settings extends Component<any, SettingsState> {
           <>
             <div>
               <a className="btn btn-secondary mb-2" href={totpUrl}>
-                {i18n.t("two_factor_link")}
+                {I18NextService.i18n.t("two_factor_link")}
               </a>
             </div>
             <div className="input-group mb-3">
@@ -901,7 +909,7 @@ export class Settings extends Component<any, SettingsState> {
                   onChange={linkEvent(this, this.handleRemoveTotp)}
                 />
                 <label className="form-check-label" htmlFor="user-remove-totp">
-                  {i18n.t("remove_two_factor")}
+                  {I18NextService.i18n.t("remove_two_factor")}
                 </label>
               </div>
             </div>
@@ -1050,7 +1058,7 @@ export class Settings extends Component<any, SettingsState> {
     // Coerce false to undefined here, so it won't generate it.
     const checked: boolean | undefined = event.target.checked || undefined;
     if (checked) {
-      toast(i18n.t("two_factor_setup_instructions"));
+      toast(I18NextService.i18n.t("two_factor_setup_instructions"));
     }
     i.setState(s => ((s.saveUserSettingsForm.generate_totp_2fa = checked), s));
   }
@@ -1078,7 +1086,9 @@ export class Settings extends Component<any, SettingsState> {
 
   handleInterfaceLangChange(i: Settings, event: any) {
     const newLang = event.target.value ?? "browser";
-    i18n.changeLanguage(newLang === "browser" ? navigator.languages : newLang);
+    I18NextService.i18n.changeLanguage(
+      newLang === "browser" ? navigator.languages : newLang
+    );
 
     i.setState(
       s => ((s.saveUserSettingsForm.interface_language = event.target.value), s)
@@ -1168,7 +1178,7 @@ export class Settings extends Component<any, SettingsState> {
     if (saveRes.state === "success") {
       UserService.Instance.login(saveRes.data);
       location.reload();
-      toast(i18n.t("saved"));
+      toast(I18NextService.i18n.t("saved"));
       window.scrollTo(0, 0);
     }
 
@@ -1191,7 +1201,7 @@ export class Settings extends Component<any, SettingsState> {
       if (changePasswordRes.state === "success") {
         UserService.Instance.login(changePasswordRes.data);
         window.scrollTo(0, 0);
-        toast(i18n.t("password_changed"));
+        toast(I18NextService.i18n.t("password_changed"));
       }
 
       i.setState({ changePasswordRes });
index 7ef5382392e8f9ec059cc710c0c062163a1ebf7c..1800c3f25753fc255b3807591cde390ea34941a5 100644 (file)
@@ -1,7 +1,7 @@
 import { setIsoData } from "@utils/app";
 import { Component } from "inferno";
 import { GetSiteResponse, VerifyEmailResponse } from "lemmy-js-client";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
 import { toast } from "../../toast";
 import { HtmlTags } from "../common/html-tags";
@@ -36,7 +36,7 @@ export class VerifyEmail extends Component<any, State> {
     });
 
     if (this.state.verifyRes.state == "success") {
-      toast(i18n.t("email_verified"));
+      toast(I18NextService.i18n.t("email_verified"));
       this.props.history.push("/login");
     }
   }
@@ -46,7 +46,7 @@ export class VerifyEmail extends Component<any, State> {
   }
 
   get documentTitle(): string {
-    return `${i18n.t("verify_email")} - ${
+    return `${I18NextService.i18n.t("verify_email")} - ${
       this.state.siteRes.site_view.site.name
     }`;
   }
@@ -60,7 +60,7 @@ export class VerifyEmail extends Component<any, State> {
         />
         <div className="row">
           <div className="col-12 col-lg-6 offset-lg-3 mb-4">
-            <h5>{i18n.t("verify_email")}</h5>
+            <h5>{I18NextService.i18n.t("verify_email")}</h5>
             {this.state.verifyRes.state == "loading" && (
               <h5>
                 <Spinner large />
index aa69038128c88abff8825f7f4494e96c4cab19c2..fe941830c6ab648ef9d05647568ef8081d2906ca 100644 (file)
@@ -11,9 +11,8 @@ import {
   GetSiteResponse,
   ListCommunitiesResponse,
 } from "lemmy-js-client";
-import { i18n } from "../../i18next";
 import { InitialFetchRequest, PostFormParams } from "../../interfaces";
-import { FirstLoadService } from "../../services/FirstLoadService";
+import { FirstLoadService, I18NextService } from "../../services";
 import {
   HttpService,
   RequestState,
@@ -143,7 +142,7 @@ export class CreatePost extends Component<
   }
 
   get documentTitle(): string {
-    return `${i18n.t("create_post")} - ${
+    return `${I18NextService.i18n.t("create_post")} - ${
       this.state.siteRes.site_view.site.name
     }`;
   }
@@ -171,7 +170,7 @@ export class CreatePost extends Component<
               id="createPostForm"
               className="col-12 col-lg-6 offset-lg-3 mb-4"
             >
-              <h1 className="h4">{i18n.t("create_post")}</h1>
+              <h1 className="h4">{I18NextService.i18n.t("create_post")}</h1>
               <PostForm
                 onCreate={this.handlePostCreate}
                 params={locationState}
index 16415d2dd78ceef885483a6393c0df5e6d8e7dd8..62b6b0fc40a17adeb709bbd8b85eee76190d0a3b 100644 (file)
@@ -2,7 +2,7 @@ import { Component, linkEvent } from "inferno";
 import { Post } from "lemmy-js-client";
 import * as sanitizeHtml from "sanitize-html";
 import { relTags } from "../../config";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 import { Icon } from "../common/icon";
 
 interface MetadataCardProps {
@@ -66,7 +66,7 @@ export class MetadataCard extends Component<
                       className="mt-2 btn btn-secondary text-monospace"
                       onClick={linkEvent(this, this.handleIframeExpand)}
                     >
-                      {i18n.t("expand_here")}
+                      {I18NextService.i18n.t("expand_here")}
                     </button>
                   )}
                 </div>
index 9385179836ba6e320556a303b663ca0601364bb6..d2793fa2810e529f2c78e0be0dd8f9c058cec1de 100644 (file)
@@ -31,9 +31,8 @@ import {
   trendingFetchLimit,
   webArchiveUrl,
 } from "../../config";
-import { i18n } from "../../i18next";
 import { PostFormParams } from "../../interfaces";
-import { UserService } from "../../services";
+import { I18NextService, UserService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
 import { setupTippy } from "../../tippy";
 import { toast } from "../../toast";
@@ -342,7 +341,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
         />
         <div className="mb-3 row">
           <label className="col-sm-2 col-form-label" htmlFor="post-url">
-            {i18n.t("url")}
+            {I18NextService.i18n.t("url")}
           </label>
           <div className="col-sm-10">
             <input
@@ -360,7 +359,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
                 className={`${
                   UserService.Instance.myUserInfo && "pointer"
                 } d-inline-block float-right text-muted font-weight-bold`}
-                data-tippy-content={i18n.t("upload_image")}
+                data-tippy-content={I18NextService.i18n.t("upload_image")}
               >
                 <Icon icon="image" classes="icon-inline" />
               </label>
@@ -381,7 +380,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
                   className="me-2 d-inline-block float-right text-muted small font-weight-bold"
                   rel={relTags}
                 >
-                  archive.org {i18n.t("archive_link")}
+                  archive.org {I18NextService.i18n.t("archive_link")}
                 </a>
                 <a
                   href={`${ghostArchiveUrl}/search?term=${encodeURIComponent(
@@ -390,7 +389,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
                   className="me-2 d-inline-block float-right text-muted small font-weight-bold"
                   rel={relTags}
                 >
-                  ghostarchive.org {i18n.t("archive_link")}
+                  ghostarchive.org {I18NextService.i18n.t("archive_link")}
                 </a>
                 <a
                   href={`${archiveTodayUrl}/?run=1&url=${encodeURIComponent(
@@ -399,7 +398,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
                   className="me-2 d-inline-block float-right text-muted small font-weight-bold"
                   rel={relTags}
                 >
-                  archive.today {i18n.t("archive_link")}
+                  archive.today {I18NextService.i18n.t("archive_link")}
                 </a>
               </div>
             )}
@@ -411,17 +410,17 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
               <button
                 className="btn btn-danger btn-sm mt-2"
                 onClick={linkEvent(this, handleImageDelete)}
-                aria-label={i18n.t("delete")}
-                data-tippy-content={i18n.t("delete")}
+                aria-label={I18NextService.i18n.t("delete")}
+                data-tippy-content={I18NextService.i18n.t("delete")}
               >
                 <Icon icon="x" classes="icon-inline me-1" />
-                {capitalizeFirstLetter(i18n.t("delete"))}
+                {capitalizeFirstLetter(I18NextService.i18n.t("delete"))}
               </button>
             )}
             {this.props.crossPosts && this.props.crossPosts.length > 0 && (
               <>
                 <div className="my-1 text-muted small font-weight-bold">
-                  {i18n.t("cross_posts")}
+                  {I18NextService.i18n.t("cross_posts")}
                 </div>
                 <PostListings
                   showCommunity
@@ -455,7 +454,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
         </div>
         <div className="mb-3 row">
           <label className="col-sm-2 col-form-label" htmlFor="post-title">
-            {i18n.t("title")}
+            {I18NextService.i18n.t("title")}
           </label>
           <div className="col-sm-10">
             <textarea
@@ -472,7 +471,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
             />
             {!validTitle(this.state.form.name) && (
               <div className="invalid-feedback">
-                {i18n.t("invalid_post_title")}
+                {I18NextService.i18n.t("invalid_post_title")}
               </div>
             )}
             {this.renderSuggestedPosts()}
@@ -480,7 +479,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
         </div>
 
         <div className="mb-3 row">
-          <label className="col-sm-2 col-form-label">{i18n.t("body")}</label>
+          <label className="col-sm-2 col-form-label">
+            {I18NextService.i18n.t("body")}
+          </label>
           <div className="col-sm-10">
             <MarkdownTextArea
               initialContent={this.state.form.body}
@@ -501,7 +502,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
         {!this.props.post_view && (
           <div className="mb-3 row">
             <label className="col-sm-2 col-form-label" htmlFor="post-community">
-              {i18n.t("community")}
+              {I18NextService.i18n.t("community")}
             </label>
             <div className="col-sm-10">
               <SearchableSelect
@@ -509,7 +510,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
                 value={this.state.form.community_id}
                 options={[
                   {
-                    label: i18n.t("select_a_community"),
+                    label: I18NextService.i18n.t("select_a_community"),
                     value: "",
                     disabled: true,
                   } as Choice,
@@ -530,7 +531,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
               checked={this.state.form.nsfw}
               onChange={linkEvent(this, handlePostNsfwChange)}
             />
-            <label className="form-check-label">{i18n.t("nsfw")}</label>
+            <label className="form-check-label">
+              {I18NextService.i18n.t("nsfw")}
+            </label>
           </div>
         )}
         <input
@@ -553,9 +556,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
               {this.state.loading ? (
                 <Spinner />
               ) : this.props.post_view ? (
-                capitalizeFirstLetter(i18n.t("save"))
+                capitalizeFirstLetter(I18NextService.i18n.t("save"))
               ) : (
-                capitalizeFirstLetter(i18n.t("create"))
+                capitalizeFirstLetter(I18NextService.i18n.t("create"))
               )}
             </button>
             {this.props.post_view && (
@@ -564,7 +567,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
                 className="btn btn-secondary"
                 onClick={linkEvent(this, handleCancel)}
               >
-                {i18n.t("cancel")}
+                {I18NextService.i18n.t("cancel")}
               </button>
             )}
           </div>
@@ -590,7 +593,8 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
                 copySuggestedTitle
               )}
             >
-              {i18n.t("copy_suggested_title", { title: "" })} {suggestedTitle}
+              {I18NextService.i18n.t("copy_suggested_title", { title: "" })}{" "}
+              {suggestedTitle}
             </div>
           )
         );
@@ -610,7 +614,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
           suggestedPosts.length > 0 && (
             <>
               <div className="my-1 text-muted small font-weight-bold">
-                {i18n.t("related_posts")}
+                {I18NextService.i18n.t("related_posts")}
               </div>
               <PostListings
                 showCommunity
index 46a31ba6ce2098e48777401f7abed757828c2453..bbc0289209c0c1a82d4eb84945310fc3b21d72d1 100644 (file)
@@ -39,10 +39,9 @@ import {
 } from "lemmy-js-client";
 import { relTags } from "../../config";
 import { getExternalHost, getHttpBase } from "../../env";
-import { i18n } from "../../i18next";
 import { BanType, PostFormParams, PurgeType, VoteType } from "../../interfaces";
 import { mdNoImages, mdToHtml, mdToHtmlInline } from "../../markdown";
-import { UserService } from "../../services";
+import { I18NextService, UserService } from "../../services";
 import { setupTippy } from "../../tippy";
 import { Icon, PurgeWarning, Spinner } from "../common/icon";
 import { MomentTime } from "../common/moment-time";
@@ -298,9 +297,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
         <a
           href={this.imageSrc}
           className="text-body d-inline-block position-relative mb-2"
-          data-tippy-content={i18n.t("expand_here")}
+          data-tippy-content={I18NextService.i18n.t("expand_here")}
           onClick={linkEvent(this, this.handleImageExpandClick)}
-          aria-label={i18n.t("expand_here")}
+          aria-label={I18NextService.i18n.t("expand_here")}
         >
           {this.imgThumb(this.imageSrc)}
           <Icon icon="image" classes="mini-overlay" />
@@ -347,7 +346,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
         <Link
           className="text-body"
           to={`/post/${post.id}`}
-          title={i18n.t("comments")}
+          title={I18NextService.i18n.t("comments")}
         >
           <div className="thumbnail rounded bg-light d-flex justify-content-center">
             <Icon icon="message-square" classes="d-flex align-items-center" />
@@ -365,20 +364,25 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
           <PersonListing person={post_view.creator} />
 
           {this.creatorIsMod_ && (
-            <span className="mx-1 badge text-bg-light">{i18n.t("mod")}</span>
+            <span className="mx-1 badge text-bg-light">
+              {I18NextService.i18n.t("mod")}
+            </span>
           )}
           {this.creatorIsAdmin_ && (
-            <span className="mx-1 badge text-bg-light">{i18n.t("admin")}</span>
+            <span className="mx-1 badge text-bg-light">
+              {I18NextService.i18n.t("admin")}
+            </span>
           )}
           {post_view.creator.bot_account && (
             <span className="mx-1 badge text-bg-light">
-              {i18n.t("bot_account").toLowerCase()}
+              {I18NextService.i18n.t("bot_account").toLowerCase()}
             </span>
           )}
           {this.props.showCommunity && (
             <>
               {" "}
-              {i18n.t("to")} <CommunityLink community={post_view.community} />
+              {I18NextService.i18n.t("to")}{" "}
+              <CommunityLink community={post_view.community} />
             </>
           )}
         </li>
@@ -412,8 +416,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
             this.postView.my_vote == 1 ? "text-info" : "text-muted"
           }`}
           onClick={linkEvent(this, this.handleUpvote)}
-          data-tippy-content={i18n.t("upvote")}
-          aria-label={i18n.t("upvote")}
+          data-tippy-content={I18NextService.i18n.t("upvote")}
+          aria-label={I18NextService.i18n.t("upvote")}
           aria-pressed={this.postView.my_vote === 1}
         >
           {this.state.upvoteLoading ? (
@@ -438,8 +442,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
               this.postView.my_vote == -1 ? "text-danger" : "text-muted"
             }`}
             onClick={linkEvent(this, this.handleDownvote)}
-            data-tippy-content={i18n.t("downvote")}
-            aria-label={i18n.t("downvote")}
+            data-tippy-content={I18NextService.i18n.t("downvote")}
+            aria-label={I18NextService.i18n.t("downvote")}
             aria-pressed={this.postView.my_vote === -1}
           >
             {this.state.downvoteLoading ? (
@@ -463,7 +467,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
             : "text-primary"
         }`}
         to={`/post/${post.id}`}
-        title={i18n.t("comments")}
+        title={I18NextService.i18n.t("comments")}
       >
         <span
           className="d-inline"
@@ -501,7 +505,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
             (post.thumbnail_url && (
               <button
                 className="btn btn-sm text-monospace text-muted d-inline-block"
-                data-tippy-content={i18n.t("expand_here")}
+                data-tippy-content={I18NextService.i18n.t("expand_here")}
                 onClick={linkEvent(this, this.handleImageExpandClick)}
               >
                 <Icon
@@ -514,13 +518,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
             ))}
           {post.removed && (
             <small className="ms-2 badge text-bg-secondary">
-              {i18n.t("removed")}
+              {I18NextService.i18n.t("removed")}
             </small>
           )}
           {post.deleted && (
             <small
               className="unselectable pointer ms-2 text-muted font-italic"
-              data-tippy-content={i18n.t("deleted")}
+              data-tippy-content={I18NextService.i18n.t("deleted")}
             >
               <Icon icon="trash" classes="icon-inline text-danger" />
             </small>
@@ -528,7 +532,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
           {post.locked && (
             <small
               className="unselectable pointer ms-2 text-muted font-italic"
-              data-tippy-content={i18n.t("locked")}
+              data-tippy-content={I18NextService.i18n.t("locked")}
             >
               <Icon icon="lock" classes="icon-inline text-danger" />
             </small>
@@ -536,8 +540,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
           {post.featured_community && (
             <small
               className="unselectable pointer ms-2 text-muted font-italic"
-              data-tippy-content={i18n.t("featured_in_community")}
-              aria-label={i18n.t("featured_in_community")}
+              data-tippy-content={I18NextService.i18n.t(
+                "featured_in_community"
+              )}
+              aria-label={I18NextService.i18n.t("featured_in_community")}
             >
               <Icon icon="pin" classes="icon-inline text-primary" />
             </small>
@@ -545,15 +551,15 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
           {post.featured_local && (
             <small
               className="unselectable pointer ms-2 text-muted font-italic"
-              data-tippy-content={i18n.t("featured_in_local")}
-              aria-label={i18n.t("featured_in_local")}
+              data-tippy-content={I18NextService.i18n.t("featured_in_local")}
+              aria-label={I18NextService.i18n.t("featured_in_local")}
             >
               <Icon icon="pin" classes="icon-inline text-secondary" />
             </small>
           )}
           {post.nsfw && (
             <small className="ms-2 badge text-bg-danger">
-              {i18n.t("nsfw")}
+              {I18NextService.i18n.t("nsfw")}
             </small>
           )}
         </div>
@@ -587,7 +593,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
     return dupes && dupes.length > 0 ? (
       <ul className="list-inline mb-1 small text-muted">
         <>
-          <li className="list-inline-item me-2">{i18n.t("cross_posted_to")}</li>
+          <li className="list-inline-item me-2">
+            {I18NextService.i18n.t("cross_posted_to")}
+          </li>
           {dupes.map(pv => (
             <li key={pv.post.id} className="list-inline-item me-2">
               <Link to={`/post/${pv.post.id}`}>
@@ -622,7 +630,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
         {!post.local && (
           <a
             className="btn btn-sm btn-animate text-muted py-0"
-            title={i18n.t("link")}
+            title={I18NextService.i18n.t("link")}
             href={post.ap_id}
           >
             <Icon icon="fedilink" inline />
@@ -681,11 +689,11 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
           <button
             className="btn btn-sm btn-animate text-muted py-0 dropdown-toggle"
             onClick={linkEvent(this, this.handleShowAdvanced)}
-            data-tippy-content={i18n.t("more")}
+            data-tippy-content={I18NextService.i18n.t("more")}
             data-bs-toggle="dropdown"
             aria-expanded="false"
             aria-controls="advancedButtonsDropdown"
-            aria-label={i18n.t("more")}
+            aria-label={I18NextService.i18n.t("more")}
           >
             <Icon icon="more-vertical" inline />
           </button>
@@ -725,7 +733,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
 
   get commentsButton() {
     const post_view = this.postView;
-    const title = i18n.t("number_of_comments", {
+    const title = I18NextService.i18n.t("number_of_comments", {
       count: Number(post_view.counts.comments),
       formattedCount: Number(post_view.counts.comments),
     });
@@ -743,7 +751,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
         </span>
         {this.unreadCount && (
           <span className="text-muted fst-italic">
-            ({this.unreadCount} {i18n.t("new")})
+            ({this.unreadCount} {I18NextService.i18n.t("new")})
           </span>
         )}
       </Link>
@@ -771,7 +779,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
             }`}
             {...tippy}
             onClick={linkEvent(this, this.handleUpvote)}
-            aria-label={i18n.t("upvote")}
+            aria-label={I18NextService.i18n.t("upvote")}
             aria-pressed={this.postView.my_vote === 1}
           >
             {this.state.upvoteLoading ? (
@@ -794,7 +802,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
               }`}
               onClick={linkEvent(this, this.handleDownvote)}
               {...tippy}
-              aria-label={i18n.t("downvote")}
+              aria-label={I18NextService.i18n.t("downvote")}
               aria-pressed={this.postView.my_vote === -1}
             >
               {this.state.downvoteLoading ? (
@@ -822,7 +830,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
 
   get saveButton() {
     const saved = this.postView.saved;
-    const label = saved ? i18n.t("unsave") : i18n.t("save");
+    const label = saved
+      ? I18NextService.i18n.t("unsave")
+      : I18NextService.i18n.t("save");
     return (
       <button
         className="btn btn-sm btn-animate text-muted py-0"
@@ -855,9 +865,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
           key: "",
           search: "",
         }}
-        title={i18n.t("cross_post")}
-        data-tippy-content={i18n.t("cross_post")}
-        aria-label={i18n.t("cross_post")}
+        title={I18NextService.i18n.t("cross_post")}
+        data-tippy-content={I18NextService.i18n.t("cross_post")}
+        aria-label={I18NextService.i18n.t("cross_post")}
       >
         <Icon icon="copy" inline />
       </Link>
@@ -869,10 +879,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
       <button
         className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
         onClick={linkEvent(this, this.handleShowReportDialog)}
-        aria-label={i18n.t("show_report_dialog")}
+        aria-label={I18NextService.i18n.t("show_report_dialog")}
       >
         <Icon classes="me-1" icon="flag" inline />
-        {i18n.t("create_report")}
+        {I18NextService.i18n.t("create_report")}
       </button>
     );
   }
@@ -882,14 +892,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
       <button
         className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
         onClick={linkEvent(this, this.handleBlockPersonClick)}
-        aria-label={i18n.t("block_user")}
+        aria-label={I18NextService.i18n.t("block_user")}
       >
         {this.state.blockLoading ? (
           <Spinner />
         ) : (
           <Icon classes="me-1" icon="slash" inline />
         )}
-        {i18n.t("block_user")}
+        {I18NextService.i18n.t("block_user")}
       </button>
     );
   }
@@ -899,17 +909,19 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
       <button
         className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
         onClick={linkEvent(this, this.handleEditClick)}
-        aria-label={i18n.t("edit")}
+        aria-label={I18NextService.i18n.t("edit")}
       >
         <Icon classes="me-1" icon="edit" inline />
-        {i18n.t("edit")}
+        {I18NextService.i18n.t("edit")}
       </button>
     );
   }
 
   get deleteButton() {
     const deleted = this.postView.post.deleted;
-    const label = !deleted ? i18n.t("delete") : i18n.t("restore");
+    const label = !deleted
+      ? I18NextService.i18n.t("delete")
+      : I18NextService.i18n.t("restore");
     return (
       <button
         className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
@@ -937,8 +949,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
       <button
         className="btn btn-sm btn-animate text-muted py-0"
         onClick={linkEvent(this, this.handleViewSource)}
-        data-tippy-content={i18n.t("view_source")}
-        aria-label={i18n.t("view_source")}
+        data-tippy-content={I18NextService.i18n.t("view_source")}
+        aria-label={I18NextService.i18n.t("view_source")}
       >
         <Icon
           icon="file-text"
@@ -951,7 +963,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
 
   get lockButton() {
     const locked = this.postView.post.locked;
-    const label = locked ? i18n.t("unlock") : i18n.t("lock");
+    const label = locked
+      ? I18NextService.i18n.t("unlock")
+      : I18NextService.i18n.t("lock");
     return (
       <button
         className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
@@ -977,13 +991,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
   get featureButtons() {
     const featuredCommunity = this.postView.post.featured_community;
     const labelCommunity = featuredCommunity
-      ? i18n.t("unfeature_from_community")
-      : i18n.t("feature_in_community");
+      ? I18NextService.i18n.t("unfeature_from_community")
+      : I18NextService.i18n.t("feature_in_community");
 
     const featuredLocal = this.postView.post.featured_local;
     const labelLocal = featuredLocal
-      ? i18n.t("unfeature_from_local")
-      : i18n.t("feature_in_local");
+      ? I18NextService.i18n.t("unfeature_from_local")
+      : I18NextService.i18n.t("feature_in_local");
     return (
       <>
         <li>
@@ -1004,7 +1018,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
                   })}
                   inline
                 />
-                {i18n.t("community")}
+                {I18NextService.i18n.t("community")}
               </>
             )}
           </button>
@@ -1028,7 +1042,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
                     })}
                     inline
                   />
-                  {i18n.t("local")}
+                  {I18NextService.i18n.t("local")}
                 </>
               )}
             </button>
@@ -1052,9 +1066,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
         {this.state.removeLoading ? (
           <Spinner />
         ) : !removed ? (
-          i18n.t("remove")
+          I18NextService.i18n.t("remove")
         ) : (
-          i18n.t("restore")
+          I18NextService.i18n.t("restore")
         )}
       </button>
     );
@@ -1079,9 +1093,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
                       this,
                       this.handleModBanFromCommunityShow
                     )}
-                    aria-label={i18n.t("ban_from_community")}
+                    aria-label={I18NextService.i18n.t("ban_from_community")}
                   >
-                    {i18n.t("ban_from_community")}
+                    {I18NextService.i18n.t("ban_from_community")}
                   </button>
                 ) : (
                   <button
@@ -1090,9 +1104,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
                       this,
                       this.handleModBanFromCommunitySubmit
                     )}
-                    aria-label={i18n.t("unban")}
+                    aria-label={I18NextService.i18n.t("unban")}
                   >
-                    {this.state.banLoading ? <Spinner /> : i18n.t("unban")}
+                    {this.state.banLoading ? (
+                      <Spinner />
+                    ) : (
+                      I18NextService.i18n.t("unban")
+                    )}
                   </button>
                 ))}
               {!post_view.creator_banned_from_community && (
@@ -1101,16 +1119,16 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
                   onClick={linkEvent(this, this.handleAddModToCommunity)}
                   aria-label={
                     this.creatorIsMod_
-                      ? i18n.t("remove_as_mod")
-                      : i18n.t("appoint_as_mod")
+                      ? I18NextService.i18n.t("remove_as_mod")
+                      : I18NextService.i18n.t("appoint_as_mod")
                   }
                 >
                   {this.state.addModLoading ? (
                     <Spinner />
                   ) : this.creatorIsMod_ ? (
-                    i18n.t("remove_as_mod")
+                    I18NextService.i18n.t("remove_as_mod")
                   ) : (
-                    i18n.t("appoint_as_mod")
+                    I18NextService.i18n.t("appoint_as_mod")
                   )}
                 </button>
               )}
@@ -1127,24 +1145,28 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
                   this,
                   this.handleShowConfirmTransferCommunity
                 )}
-                aria-label={i18n.t("transfer_community")}
+                aria-label={I18NextService.i18n.t("transfer_community")}
               >
-                {i18n.t("transfer_community")}
+                {I18NextService.i18n.t("transfer_community")}
               </button>
             ) : (
               <>
                 <button
                   className="d-inline-block me-1 btn btn-link btn-animate text-muted py-0"
-                  aria-label={i18n.t("are_you_sure")}
+                  aria-label={I18NextService.i18n.t("are_you_sure")}
                 >
-                  {i18n.t("are_you_sure")}
+                  {I18NextService.i18n.t("are_you_sure")}
                 </button>
                 <button
                   className="btn btn-link btn-animate text-muted py-0 d-inline-block me-1"
-                  aria-label={i18n.t("yes")}
+                  aria-label={I18NextService.i18n.t("yes")}
                   onClick={linkEvent(this, this.handleTransferCommunity)}
                 >
-                  {this.state.transferLoading ? <Spinner /> : i18n.t("yes")}
+                  {this.state.transferLoading ? (
+                    <Spinner />
+                  ) : (
+                    I18NextService.i18n.t("yes")
+                  )}
                 </button>
                 <button
                   className="btn btn-link btn-animate text-muted py-0 d-inline-block"
@@ -1152,9 +1174,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
                     this,
                     this.handleCancelShowConfirmTransferCommunity
                   )}
-                  aria-label={i18n.t("no")}
+                  aria-label={I18NextService.i18n.t("no")}
                 >
-                  {i18n.t("no")}
+                  {I18NextService.i18n.t("no")}
                 </button>
               </>
             ))}
@@ -1167,36 +1189,36 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
                     <button
                       className="btn btn-link btn-animate text-muted py-0"
                       onClick={linkEvent(this, this.handleModBanShow)}
-                      aria-label={i18n.t("ban_from_site")}
+                      aria-label={I18NextService.i18n.t("ban_from_site")}
                     >
-                      {i18n.t("ban_from_site")}
+                      {I18NextService.i18n.t("ban_from_site")}
                     </button>
                   ) : (
                     <button
                       className="btn btn-link btn-animate text-muted py-0"
                       onClick={linkEvent(this, this.handleModBanSubmit)}
-                      aria-label={i18n.t("unban_from_site")}
+                      aria-label={I18NextService.i18n.t("unban_from_site")}
                     >
                       {this.state.banLoading ? (
                         <Spinner />
                       ) : (
-                        i18n.t("unban_from_site")
+                        I18NextService.i18n.t("unban_from_site")
                       )}
                     </button>
                   )}
                   <button
                     className="btn btn-link btn-animate text-muted py-0"
                     onClick={linkEvent(this, this.handlePurgePersonShow)}
-                    aria-label={i18n.t("purge_user")}
+                    aria-label={I18NextService.i18n.t("purge_user")}
                   >
-                    {i18n.t("purge_user")}
+                    {I18NextService.i18n.t("purge_user")}
                   </button>
                   <button
                     className="btn btn-link btn-animate text-muted py-0"
                     onClick={linkEvent(this, this.handlePurgePostShow)}
-                    aria-label={i18n.t("purge_post")}
+                    aria-label={I18NextService.i18n.t("purge_post")}
                   >
-                    {i18n.t("purge_post")}
+                    {I18NextService.i18n.t("purge_post")}
                   </button>
                 </>
               )}
@@ -1206,16 +1228,16 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
                   onClick={linkEvent(this, this.handleAddAdmin)}
                   aria-label={
                     this.creatorIsAdmin_
-                      ? i18n.t("remove_as_admin")
-                      : i18n.t("appoint_as_admin")
+                      ? I18NextService.i18n.t("remove_as_admin")
+                      : I18NextService.i18n.t("appoint_as_admin")
                   }
                 >
                   {this.state.addAdminLoading ? (
                     <Spinner />
                   ) : this.creatorIsAdmin_ ? (
-                    i18n.t("remove_as_admin")
+                    I18NextService.i18n.t("remove_as_admin")
                   ) : (
-                    i18n.t("appoint_as_admin")
+                    I18NextService.i18n.t("appoint_as_admin")
                   )}
                 </button>
               )}
@@ -1230,8 +1252,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
     const post = this.postView;
     const purgeTypeText =
       this.state.purgeType == PurgeType.Post
-        ? i18n.t("purge_post")
-        : `${i18n.t("purge")} ${post.creator.name}`;
+        ? I18NextService.i18n.t("purge_post")
+        : `${I18NextService.i18n.t("purge")} ${post.creator.name}`;
     return (
       <>
         {this.state.showRemoveDialog && (
@@ -1243,22 +1265,26 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
               className="visually-hidden"
               htmlFor="post-listing-remove-reason"
             >
-              {i18n.t("reason")}
+              {I18NextService.i18n.t("reason")}
             </label>
             <input
               type="text"
               id="post-listing-remove-reason"
               className="form-control me-2"
-              placeholder={i18n.t("reason")}
+              placeholder={I18NextService.i18n.t("reason")}
               value={this.state.removeReason}
               onInput={linkEvent(this, this.handleModRemoveReasonChange)}
             />
             <button
               type="submit"
               className="btn btn-secondary"
-              aria-label={i18n.t("remove_post")}
+              aria-label={I18NextService.i18n.t("remove_post")}
             >
-              {this.state.removeLoading ? <Spinner /> : i18n.t("remove_post")}
+              {this.state.removeLoading ? (
+                <Spinner />
+              ) : (
+                I18NextService.i18n.t("remove_post")
+              )}
             </button>
           </form>
         )}
@@ -1269,24 +1295,24 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
                 className="col-form-label"
                 htmlFor="post-listing-ban-reason"
               >
-                {i18n.t("reason")}
+                {I18NextService.i18n.t("reason")}
               </label>
               <input
                 type="text"
                 id="post-listing-ban-reason"
                 className="form-control me-2"
-                placeholder={i18n.t("reason")}
+                placeholder={I18NextService.i18n.t("reason")}
                 value={this.state.banReason}
                 onInput={linkEvent(this, this.handleModBanReasonChange)}
               />
               <label className="col-form-label" htmlFor={`mod-ban-expires`}>
-                {i18n.t("expires")}
+                {I18NextService.i18n.t("expires")}
               </label>
               <input
                 type="number"
                 id={`mod-ban-expires`}
                 className="form-control me-2"
-                placeholder={i18n.t("number_of_days")}
+                placeholder={I18NextService.i18n.t("number_of_days")}
                 value={this.state.banExpireDays}
                 onInput={linkEvent(this, this.handleModBanExpireDaysChange)}
               />
@@ -1302,9 +1328,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
                   <label
                     className="form-check-label"
                     htmlFor="mod-ban-remove-data"
-                    title={i18n.t("remove_content_more")}
+                    title={I18NextService.i18n.t("remove_content_more")}
                   >
-                    {i18n.t("remove_content")}
+                    {I18NextService.i18n.t("remove_content")}
                   </label>
                 </div>
               </div>
@@ -1312,19 +1338,19 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
             {/* TODO hold off on expires until later */}
             {/* <div class="mb-3 row"> */}
             {/*   <label class="col-form-label">Expires</label> */}
-            {/*   <input type="date" class="form-control me-2" placeholder={i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
+            {/*   <input type="date" class="form-control me-2" placeholder={I18NextService.i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
             {/* </div> */}
             <div className="mb-3 row">
               <button
                 type="submit"
                 className="btn btn-secondary"
-                aria-label={i18n.t("ban")}
+                aria-label={I18NextService.i18n.t("ban")}
               >
                 {this.state.banLoading ? (
                   <Spinner />
                 ) : (
                   <span>
-                    {i18n.t("ban")} {post.creator.name}
+                    {I18NextService.i18n.t("ban")} {post.creator.name}
                   </span>
                 )}
               </button>
@@ -1337,13 +1363,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
             onSubmit={linkEvent(this, this.handleReportSubmit)}
           >
             <label className="visually-hidden" htmlFor="post-report-reason">
-              {i18n.t("reason")}
+              {I18NextService.i18n.t("reason")}
             </label>
             <input
               type="text"
               id="post-report-reason"
               className="form-control me-2"
-              placeholder={i18n.t("reason")}
+              placeholder={I18NextService.i18n.t("reason")}
               required
               value={this.state.reportReason}
               onInput={linkEvent(this, this.handleReportReasonChange)}
@@ -1351,9 +1377,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
             <button
               type="submit"
               className="btn btn-secondary"
-              aria-label={i18n.t("create_report")}
+              aria-label={I18NextService.i18n.t("create_report")}
             >
-              {this.state.reportLoading ? <Spinner /> : i18n.t("create_report")}
+              {this.state.reportLoading ? (
+                <Spinner />
+              ) : (
+                I18NextService.i18n.t("create_report")
+              )}
             </button>
           </form>
         )}
@@ -1364,13 +1394,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
           >
             <PurgeWarning />
             <label className="visually-hidden" htmlFor="purge-reason">
-              {i18n.t("reason")}
+              {I18NextService.i18n.t("reason")}
             </label>
             <input
               type="text"
               id="purge-reason"
               className="form-control me-2"
-              placeholder={i18n.t("reason")}
+              placeholder={I18NextService.i18n.t("reason")}
               value={this.state.purgeReason}
               onInput={linkEvent(this, this.handlePurgeReasonChange)}
             />
@@ -1565,10 +1595,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
     const body = post.body;
 
     return body
-      ? `${i18n.t("cross_posted_from")} ${post.ap_id}\n\n${body.replace(
-          /^/gm,
-          "> "
-        )}`
+      ? `${I18NextService.i18n.t("cross_posted_from")} ${
+          post.ap_id
+        }\n\n${body.replace(/^/gm, "> ")}`
       : undefined;
   }
 
@@ -1830,17 +1859,17 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
   }
 
   get pointsTippy(): string {
-    const points = i18n.t("number_of_points", {
+    const points = I18NextService.i18n.t("number_of_points", {
       count: Number(this.postView.counts.score),
       formattedCount: Number(this.postView.counts.score),
     });
 
-    const upvotes = i18n.t("number_of_upvotes", {
+    const upvotes = I18NextService.i18n.t("number_of_upvotes", {
       count: Number(this.postView.counts.upvotes),
       formattedCount: Number(this.postView.counts.upvotes),
     });
 
-    const downvotes = i18n.t("number_of_downvotes", {
+    const downvotes = I18NextService.i18n.t("number_of_downvotes", {
       count: Number(this.postView.counts.downvotes),
       formattedCount: Number(this.postView.counts.downvotes),
     });
index 1b2e9e8666d6d281be12caf50c2f0efcbfbd7d16..1fdaeba2ca40f1aa1f45bbdae292f3c3a908d5cc 100644 (file)
@@ -21,7 +21,7 @@ import {
   SavePost,
   TransferCommunity,
 } from "lemmy-js-client";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 import { PostListing } from "./post-listing";
 
 interface PostListingsProps {
@@ -101,7 +101,7 @@ export class PostListings extends Component<PostListingsProps, any> {
           ))
         ) : (
           <>
-            <div>{i18n.t("no_posts")}</div>
+            <div>{I18NextService.i18n.t("no_posts")}</div>
             {this.props.showCommunity && (
               <T i18nKey="subscribe_to_communities">
                 #<Link to="/communities">#</Link>
index 8af525d0d283414ef6cb0c87f622464fc54f5212..9b2540be1d18f2d0012f2a1ae43080d1a2681e8d 100644 (file)
@@ -2,7 +2,7 @@ import { myAuthRequired } from "@utils/app";
 import { Component, InfernoNode, linkEvent } from "inferno";
 import { T } from "inferno-i18next-dess";
 import { PostReportView, PostView, ResolvePostReport } from "lemmy-js-client";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 import { Icon, Spinner } from "../common/icon";
 import { PersonListing } from "../person/person-listing";
 import { PostListing } from "./post-listing";
@@ -37,7 +37,7 @@ export class PostReport extends Component<PostReportProps, PostReportState> {
     const r = this.props.report;
     const resolver = r.resolver;
     const post = r.post;
-    const tippyContent = i18n.t(
+    const tippyContent = I18NextService.i18n.t(
       r.post_report.resolved ? "unresolve_report" : "resolve_report"
     );
 
@@ -89,10 +89,11 @@ export class PostReport extends Component<PostReportProps, PostReportState> {
           onTransferCommunity={() => {}}
         />
         <div>
-          {i18n.t("reporter")}: <PersonListing person={r.creator} />
+          {I18NextService.i18n.t("reporter")}:{" "}
+          <PersonListing person={r.creator} />
         </div>
         <div>
-          {i18n.t("reason")}: {r.post_report.reason}
+          {I18NextService.i18n.t("reason")}: {r.post_report.reason}
         </div>
         {resolver && (
           <div>
index 31fc2e7023c472b50853e35b755c24f2c12b15ad..f0aa3ff5bfc60b5a6bd40cdcff11cf0b551bc1da 100644 (file)
@@ -76,14 +76,12 @@ import {
   TransferCommunity,
 } from "lemmy-js-client";
 import { commentTreeMaxDepth } from "../../config";
-import { i18n } from "../../i18next";
 import {
   CommentNodeI,
   CommentViewType,
   InitialFetchRequest,
 } from "../../interfaces";
-import { UserService } from "../../services";
-import { FirstLoadService } from "../../services/FirstLoadService";
+import { FirstLoadService, I18NextService, UserService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
 import { setupTippy } from "../../tippy";
 import { toast } from "../../toast";
@@ -400,7 +398,7 @@ export class Post extends Component<any, PostState> {
                   className="btn btn-secondary d-inline-block mb-2 me-3"
                   onClick={linkEvent(this, this.handleShowSidebarMobile)}
                 >
-                  {i18n.t("sidebar")}{" "}
+                  {I18NextService.i18n.t("sidebar")}{" "}
                   <Icon
                     icon={
                       this.state.showSidebarMobile
@@ -438,7 +436,7 @@ export class Post extends Component<any, PostState> {
               this.state.commentSort === "Hot" && "active"
             }`}
           >
-            {i18n.t("hot")}
+            {I18NextService.i18n.t("hot")}
             <input
               type="radio"
               className="btn-check"
@@ -452,7 +450,7 @@ export class Post extends Component<any, PostState> {
               this.state.commentSort === "Top" && "active"
             }`}
           >
-            {i18n.t("top")}
+            {I18NextService.i18n.t("top")}
             <input
               type="radio"
               className="btn-check"
@@ -466,7 +464,7 @@ export class Post extends Component<any, PostState> {
               this.state.commentSort === "New" && "active"
             }`}
           >
-            {i18n.t("new")}
+            {I18NextService.i18n.t("new")}
             <input
               type="radio"
               className="btn-check"
@@ -480,7 +478,7 @@ export class Post extends Component<any, PostState> {
               this.state.commentSort === "Old" && "active"
             }`}
           >
-            {i18n.t("old")}
+            {I18NextService.i18n.t("old")}
             <input
               type="radio"
               className="btn-check"
@@ -496,7 +494,7 @@ export class Post extends Component<any, PostState> {
               this.state.commentViewType === CommentViewType.Flat && "active"
             }`}
           >
-            {i18n.t("chat")}
+            {I18NextService.i18n.t("chat")}
             <input
               type="radio"
               className="btn-check"
@@ -595,14 +593,14 @@ export class Post extends Component<any, PostState> {
                 className="ps-0 d-block btn btn-link text-muted"
                 onClick={linkEvent(this, this.handleViewPost)}
               >
-                {i18n.t("view_all_comments")} ➔
+                {I18NextService.i18n.t("view_all_comments")} ➔
               </button>
               {showContextButton && (
                 <button
                   className="ps-0 d-block btn btn-link text-muted"
                   onClick={linkEvent(this, this.handleViewContext)}
                 >
-                  {i18n.t("show_context")} ➔
+                  {I18NextService.i18n.t("show_context")} ➔
                 </button>
               )}
             </>
@@ -836,14 +834,14 @@ export class Post extends Component<any, PostState> {
   async handleCommentReport(form: CreateCommentReport) {
     const reportRes = await HttpService.client.createCommentReport(form);
     if (reportRes.state == "success") {
-      toast(i18n.t("report_created"));
+      toast(I18NextService.i18n.t("report_created"));
     }
   }
 
   async handlePostReport(form: CreatePostReport) {
     const reportRes = await HttpService.client.createPostReport(form);
     if (reportRes.state == "success") {
-      toast(i18n.t("report_created"));
+      toast(I18NextService.i18n.t("report_created"));
     }
   }
 
@@ -982,7 +980,7 @@ export class Post extends Component<any, PostState> {
 
   purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
     if (purgeRes.state == "success") {
-      toast(i18n.t("purge_success"));
+      toast(I18NextService.i18n.t("purge_success"));
       this.context.router.history.push(`/`);
     }
   }
index 0bc704cf78601f3b6fc643ac4fdf2ebe044e707a..8afd3488425edec8641bc9545b3fd5b0f11a6411 100644 (file)
@@ -7,9 +7,8 @@ import {
   GetPersonDetailsResponse,
   GetSiteResponse,
 } from "lemmy-js-client";
-import { i18n } from "../../i18next";
 import { InitialFetchRequest } from "../../interfaces";
-import { FirstLoadService } from "../../services/FirstLoadService";
+import { FirstLoadService, I18NextService } from "../../services";
 import { HttpService, RequestState } from "../../services/HttpService";
 import { toast } from "../../toast";
 import { HtmlTags } from "../common/html-tags";
@@ -97,7 +96,7 @@ export class CreatePrivateMessage extends Component<
   get documentTitle(): string {
     if (this.state.recipientRes.state == "success") {
       const name_ = this.state.recipientRes.data.person_view.person.name;
-      return `${i18n.t("create_private_message")} - ${name_}`;
+      return `${I18NextService.i18n.t("create_private_message")} - ${name_}`;
     } else {
       return "";
     }
@@ -116,7 +115,7 @@ export class CreatePrivateMessage extends Component<
         return (
           <div className="row">
             <div className="col-12 col-lg-6 offset-lg-3 mb-4">
-              <h5>{i18n.t("create_private_message")}</h5>
+              <h5>{I18NextService.i18n.t("create_private_message")}</h5>
               <PrivateMessageForm
                 onCreate={this.handlePrivateMessageCreate}
                 recipient={res.person_view.person}
@@ -144,7 +143,7 @@ export class CreatePrivateMessage extends Component<
     const res = await HttpService.client.createPrivateMessage(form);
 
     if (res.state == "success") {
-      toast(i18n.t("message_sent"));
+      toast(I18NextService.i18n.t("message_sent"));
 
       // Navigate to the front
       this.context.router.history.push("/");
index 1b9cb50c74c79c4b4758171ae0e4b73e46e59a7e..338584b393ea3e6c1aa077c7dc2b0c83bd679719 100644 (file)
@@ -9,7 +9,7 @@ import {
   PrivateMessageView,
 } from "lemmy-js-client";
 import { relTags } from "../../config";
-import { i18n } from "../../i18next";
+import { I18NextService } from "../../services";
 import { setupTippy } from "../../tippy";
 import { Icon, Spinner } from "../common/icon";
 import { MarkdownTextArea } from "../common/markdown-textarea";
@@ -66,7 +66,7 @@ export class PrivateMessageForm extends Component<
   // TODO
   // <Prompt
   //   when={!this.state.loading && this.state.content}
-  //   message={i18n.t("block_leaving")}
+  //   message={I18NextService.i18n.t("block_leaving")}
   // />
 
   render() {
@@ -83,7 +83,7 @@ export class PrivateMessageForm extends Component<
         {!this.props.privateMessageView && (
           <div className="mb-3 row">
             <label className="col-sm-2 col-form-label">
-              {capitalizeFirstLetter(i18n.t("to"))}
+              {capitalizeFirstLetter(I18NextService.i18n.t("to"))}
             </label>
 
             <div className="col-sm-10 form-control-plaintext">
@@ -93,12 +93,14 @@ export class PrivateMessageForm extends Component<
         )}
         <div className="mb-3 row">
           <label className="col-sm-2 col-form-label">
-            {i18n.t("message")}
+            {I18NextService.i18n.t("message")}
             <button
               className="btn btn-link text-warning d-inline-block"
               onClick={linkEvent(this, this.handleShowDisclaimer)}
-              data-tippy-content={i18n.t("private_message_disclaimer")}
-              aria-label={i18n.t("private_message_disclaimer")}
+              data-tippy-content={I18NextService.i18n.t(
+                "private_message_disclaimer"
+              )}
+              aria-label={I18NextService.i18n.t("private_message_disclaimer")}
             >
               <Icon icon="alert-triangle" classes="icon-inline" />
             </button>
@@ -142,9 +144,9 @@ export class PrivateMessageForm extends Component<
               {this.state.loading ? (
                 <Spinner />
               ) : this.props.privateMessageView ? (
-                capitalizeFirstLetter(i18n.t("save"))
+                capitalizeFirstLetter(I18NextService.i18n.t("save"))
               ) : (
-                capitalizeFirstLetter(i18n.t("send_message"))
+                capitalizeFirstLetter(I18NextService.i18n.t("send_message"))
               )}
             </button>
             {this.props.privateMessageView && (
@@ -153,7 +155,7 @@ export class PrivateMessageForm extends Component<
                 className="btn btn-secondary"
                 onClick={linkEvent(this, this.handleCancel)}
               >
-                {i18n.t("cancel")}
+                {I18NextService.i18n.t("cancel")}
               </button>
             )}
             <ul className="d-inline-block float-right list-inline mb-1 text-muted font-weight-bold">
index 38a20d857755ab615cfcae2c14dfdc13855d78a7..d15f18c5280587ced80617b5c4da0b5f12d93355 100644 (file)
@@ -5,8 +5,8 @@ import {
   PrivateMessageReportView,
   ResolvePrivateMessageReport,
 } from "lemmy-js-client";
-import { i18n } from "../../i18next";
 import { mdToHtml } from "../../markdown";
+import { I18NextService } from "../../services";
 import { Icon, Spinner } from "../common/icon";
 import { PersonListing } from "../person/person-listing";
 
@@ -39,28 +39,29 @@ export class PrivateMessageReport extends Component<Props, State> {
   render() {
     const r = this.props.report;
     const pmr = r.private_message_report;
-    const tippyContent = i18n.t(
+    const tippyContent = I18NextService.i18n.t(
       r.private_message_report.resolved ? "unresolve_report" : "resolve_report"
     );
 
     return (
       <div className="private-message-report">
         <div>
-          {i18n.t("creator")}:{" "}
+          {I18NextService.i18n.t("creator")}:{" "}
           <PersonListing person={r.private_message_creator} />
         </div>
         <div>
-          {i18n.t("message")}:
+          {I18NextService.i18n.t("message")}:
           <div
             className="md-div"
             dangerouslySetInnerHTML={mdToHtml(pmr.original_pm_text)}
           />
         </div>
         <div>
-          {i18n.t("reporter")}: <PersonListing person={r.creator} />
+          {I18NextService.i18n.t("reporter")}:{" "}
+          <PersonListing person={r.creator} />
         </div>
         <div>
-          {i18n.t("reason")}: {pmr.reason}
+          {I18NextService.i18n.t("reason")}: {pmr.reason}
         </div>
         {r.resolver && (
           <div>
index db40604c3fac3455d8a0d3ab7f52eba0d155504b..af8d64e5110ff64d0f65de8f7f0c57c288380de5 100644 (file)
@@ -9,9 +9,8 @@ import {
   Person,
   PrivateMessageView,
 } from "lemmy-js-client";
-import { i18n } from "../../i18next";
 import { mdToHtml } from "../../markdown";
-import { UserService } from "../../services";
+import { I18NextService, UserService } from "../../services";
 import { Icon, Spinner } from "../common/icon";
 import { MomentTime } from "../common/moment-time";
 import { PersonListing } from "../person/person-listing";
@@ -94,7 +93,9 @@ export class PrivateMessage extends Component<
           <ul className="list-inline mb-0 text-muted small">
             {/* TODO refactor this */}
             <li className="list-inline-item">
-              {this.mine ? i18n.t("to") : i18n.t("from")}
+              {this.mine
+                ? I18NextService.i18n.t("to")
+                : I18NextService.i18n.t("from")}
             </li>
             <li className="list-inline-item">
               <PersonListing person={otherPerson} />
@@ -148,13 +149,13 @@ export class PrivateMessage extends Component<
                         onClick={linkEvent(this, this.handleMarkRead)}
                         data-tippy-content={
                           message_view.private_message.read
-                            ? i18n.t("mark_as_unread")
-                            : i18n.t("mark_as_read")
+                            ? I18NextService.i18n.t("mark_as_unread")
+                            : I18NextService.i18n.t("mark_as_read")
                         }
                         aria-label={
                           message_view.private_message.read
-                            ? i18n.t("mark_as_unread")
-                            : i18n.t("mark_as_read")
+                            ? I18NextService.i18n.t("mark_as_unread")
+                            : I18NextService.i18n.t("mark_as_read")
                         }
                       >
                         {this.state.readLoading ? (
@@ -175,8 +176,8 @@ export class PrivateMessage extends Component<
                       <button
                         className="btn btn-link btn-animate text-muted"
                         onClick={linkEvent(this, this.handleReplyClick)}
-                        data-tippy-content={i18n.t("reply")}
-                        aria-label={i18n.t("reply")}
+                        data-tippy-content={I18NextService.i18n.t("reply")}
+                        aria-label={I18NextService.i18n.t("reply")}
                       >
                         <Icon icon="reply1" classes="icon-inline" />
                       </button>
@@ -189,8 +190,8 @@ export class PrivateMessage extends Component<
                       <button
                         className="btn btn-link btn-animate text-muted"
                         onClick={linkEvent(this, this.handleEditClick)}
-                        data-tippy-content={i18n.t("edit")}
-                        aria-label={i18n.t("edit")}
+                        data-tippy-content={I18NextService.i18n.t("edit")}
+                        aria-label={I18NextService.i18n.t("edit")}
                       >
                         <Icon icon="edit" classes="icon-inline" />
                       </button>
@@ -201,13 +202,13 @@ export class PrivateMessage extends Component<
                         onClick={linkEvent(this, this.handleDeleteClick)}
                         data-tippy-content={
                           !message_view.private_message.deleted
-                            ? i18n.t("delete")
-                            : i18n.t("restore")
+                            ? I18NextService.i18n.t("delete")
+                            : I18NextService.i18n.t("restore")
                         }
                         aria-label={
                           !message_view.private_message.deleted
-                            ? i18n.t("delete")
-                            : i18n.t("restore")
+                            ? I18NextService.i18n.t("delete")
+                            : I18NextService.i18n.t("restore")
                         }
                       >
                         {this.state.deleteLoading ? (
@@ -229,8 +230,8 @@ export class PrivateMessage extends Component<
                   <button
                     className="btn btn-link btn-animate text-muted"
                     onClick={linkEvent(this, this.handleViewSource)}
-                    data-tippy-content={i18n.t("view_source")}
-                    aria-label={i18n.t("view_source")}
+                    data-tippy-content={I18NextService.i18n.t("view_source")}
+                    aria-label={I18NextService.i18n.t("view_source")}
                   >
                     <Icon
                       icon="file-text"
@@ -250,13 +251,13 @@ export class PrivateMessage extends Component<
             onSubmit={linkEvent(this, this.handleReportSubmit)}
           >
             <label className="visually-hidden" htmlFor="pm-report-reason">
-              {i18n.t("reason")}
+              {I18NextService.i18n.t("reason")}
             </label>
             <input
               type="text"
               id="pm-report-reason"
               className="form-control me-2"
-              placeholder={i18n.t("reason")}
+              placeholder={I18NextService.i18n.t("reason")}
               required
               value={this.state.reportReason}
               onInput={linkEvent(this, this.handleReportReasonChange)}
@@ -264,9 +265,13 @@ export class PrivateMessage extends Component<
             <button
               type="submit"
               className="btn btn-secondary"
-              aria-label={i18n.t("create_report")}
+              aria-label={I18NextService.i18n.t("create_report")}
             >
-              {this.state.reportLoading ? <Spinner /> : i18n.t("create_report")}
+              {this.state.reportLoading ? (
+                <Spinner />
+              ) : (
+                I18NextService.i18n.t("create_report")
+              )}
             </button>
           </form>
         )}
@@ -287,8 +292,8 @@ export class PrivateMessage extends Component<
       <button
         className="btn btn-link btn-animate text-muted py-0"
         onClick={linkEvent(this, this.handleShowReportDialog)}
-        data-tippy-content={i18n.t("show_report_dialog")}
-        aria-label={i18n.t("show_report_dialog")}
+        data-tippy-content={I18NextService.i18n.t("show_report_dialog")}
+        aria-label={I18NextService.i18n.t("show_report_dialog")}
       >
         <Icon icon="flag" inline />
       </button>
@@ -297,7 +302,9 @@ export class PrivateMessage extends Component<
 
   get messageUnlessRemoved(): string {
     const message = this.props.private_message_view.private_message;
-    return message.deleted ? `*${i18n.t("deleted")}*` : message.content;
+    return message.deleted
+      ? `*${I18NextService.i18n.t("deleted")}*`
+      : message.content;
   }
 
   handleReplyClick(i: PrivateMessage) {
index 72ea05a0a9c604ac6927aee0150db4e4df8a6673..473b18c483c430177a5a011dd825ece643f19387 100644 (file)
@@ -46,9 +46,8 @@ import {
   SortType,
 } from "lemmy-js-client";
 import { fetchLimit } from "../config";
-import { i18n } from "../i18next";
 import { CommentViewType, InitialFetchRequest } from "../interfaces";
-import { FirstLoadService } from "../services/FirstLoadService";
+import { FirstLoadService, I18NextService } from "../services";
 import { HttpService, RequestState } from "../services/HttpService";
 import { CommentNodes } from "./comment/comment-nodes";
 import { HtmlTags } from "./common/html-tags";
@@ -184,13 +183,13 @@ const Filter = ({
   return (
     <div className="mb-3 col-sm-6">
       <label className="col-form-label me-2" htmlFor={`${filterType}-filter`}>
-        {capitalizeFirstLetter(i18n.t(filterType))}
+        {capitalizeFirstLetter(I18NextService.i18n.t(filterType))}
       </label>
       <SearchableSelect
         id={`${filterType}-filter`}
         options={[
           {
-            label: i18n.t("all"),
+            label: I18NextService.i18n.t("all"),
             value: "0",
           },
         ].concat(options)}
@@ -228,7 +227,7 @@ function getListing(
   return (
     <>
       <span>{listing}</span>
-      <span>{` - ${i18n.t(translationKey, {
+      <span>{` - ${I18NextService.i18n.t(translationKey, {
         count: Number(count),
         formattedCount: numToSI(count),
       })}`}</span>
@@ -448,7 +447,7 @@ export class Search extends Component<any, SearchState> {
   get documentTitle(): string {
     const { q } = getSearchQueryParams();
     const name = this.state.siteRes.site_view.site.name;
-    return `${i18n.t("search")} - ${q ? `${q} - ` : ""}${name}`;
+    return `${I18NextService.i18n.t("search")} - ${q ? `${q} - ` : ""}${name}`;
   }
 
   render() {
@@ -460,13 +459,13 @@ export class Search extends Component<any, SearchState> {
           title={this.documentTitle}
           path={this.context.router.route.match.url}
         />
-        <h5>{i18n.t("search")}</h5>
+        <h5>{I18NextService.i18n.t("search")}</h5>
         {this.selects}
         {this.searchForm}
         {this.displayResults(type)}
         {this.resultsCount === 0 &&
           this.state.searchRes.state === "success" && (
-            <span>{i18n.t("no_results")}</span>
+            <span>{I18NextService.i18n.t("no_results")}</span>
           )}
         <Paginator page={page} onChange={this.handlePageChange} />
       </div>
@@ -499,8 +498,8 @@ export class Search extends Component<any, SearchState> {
             type="text"
             className="form-control me-2 mb-2 col-sm-8"
             value={this.state.searchText}
-            placeholder={`${i18n.t("search")}...`}
-            aria-label={i18n.t("search")}
+            placeholder={`${I18NextService.i18n.t("search")}...`}
+            aria-label={I18NextService.i18n.t("search")}
             onInput={linkEvent(this, this.handleQChange)}
             required
             minLength={1}
@@ -511,7 +510,7 @@ export class Search extends Component<any, SearchState> {
             {this.state.searchRes.state === "loading" ? (
               <Spinner />
             ) : (
-              <span>{i18n.t("search")}</span>
+              <span>{I18NextService.i18n.t("search")}</span>
             )}
           </button>
         </div>
@@ -540,14 +539,16 @@ export class Search extends Component<any, SearchState> {
           value={type}
           onChange={linkEvent(this, this.handleTypeChange)}
           className="form-select d-inline-block w-auto mb-2"
-          aria-label={i18n.t("type")}
+          aria-label={I18NextService.i18n.t("type")}
         >
           <option disabled aria-hidden="true">
-            {i18n.t("type")}
+            {I18NextService.i18n.t("type")}
           </option>
           {searchTypes.map(option => (
             <option value={option} key={option}>
-              {i18n.t(option.toString().toLowerCase() as NoOptionI18nKeys)}
+              {I18NextService.i18n.t(
+                option.toString().toLowerCase() as NoOptionI18nKeys
+              )}
             </option>
           ))}
         </select>
index f6c30167d9843bfc4ac0f341050083d4daf1949f..6f57ecb502b5f77e9e9f1462d7d5f33d1eb97795 100644 (file)
@@ -1,7 +1,7 @@
 import { LemmyHttp } from "lemmy-js-client";
 import { getHttpBase } from "../../shared/env";
-import { i18n } from "../../shared/i18next";
 import { toast } from "../../shared/toast";
+import { I18NextService } from "./I18NextService";
 
 type EmptyRequestState = {
   state: "empty";
@@ -62,7 +62,7 @@ class WrappedLemmyHttpClient {
             };
           } catch (error) {
             console.error(`API error: ${error}`);
-            toast(i18n.t(error), "danger");
+            toast(I18NextService.i18n.t(error), "danger");
             return {
               state: "failed",
               msg: error,
similarity index 53%
rename from src/shared/i18next.ts
rename to src/shared/services/I18NextService.ts
index aab43014b575026e4698ac5e16f9cf36ff9f7ba0..a7e8c979c017f707fcebc5bb61a65b1900974cd6 100644 (file)
@@ -1,37 +1,37 @@
 import { isBrowser } from "@utils/browser";
-import i18next, { i18nTyped, Resource } from "i18next";
-import { UserService } from "./services/UserService";
-import { ar } from "./translations/ar";
-import { bg } from "./translations/bg";
-import { ca } from "./translations/ca";
-import { cs } from "./translations/cs";
-import { da } from "./translations/da";
-import { de } from "./translations/de";
-import { el } from "./translations/el";
-import { en } from "./translations/en";
-import { eo } from "./translations/eo";
-import { es } from "./translations/es";
-import { eu } from "./translations/eu";
-import { fa } from "./translations/fa";
-import { fi } from "./translations/fi";
-import { fr } from "./translations/fr";
-import { ga } from "./translations/ga";
-import { gl } from "./translations/gl";
-import { hr } from "./translations/hr";
-import { id } from "./translations/id";
-import { it } from "./translations/it";
-import { ja } from "./translations/ja";
-import { ko } from "./translations/ko";
-import { nl } from "./translations/nl";
-import { oc } from "./translations/oc";
-import { pl } from "./translations/pl";
-import { pt } from "./translations/pt";
-import { pt_BR } from "./translations/pt_BR";
-import { ru } from "./translations/ru";
-import { sv } from "./translations/sv";
-import { vi } from "./translations/vi";
-import { zh } from "./translations/zh";
-import { zh_Hant } from "./translations/zh_Hant";
+import i18next, { Resource } from "i18next";
+import { UserService } from "../services";
+import { ar } from "../translations/ar";
+import { bg } from "../translations/bg";
+import { ca } from "../translations/ca";
+import { cs } from "../translations/cs";
+import { da } from "../translations/da";
+import { de } from "../translations/de";
+import { el } from "../translations/el";
+import { en } from "../translations/en";
+import { eo } from "../translations/eo";
+import { es } from "../translations/es";
+import { eu } from "../translations/eu";
+import { fa } from "../translations/fa";
+import { fi } from "../translations/fi";
+import { fr } from "../translations/fr";
+import { ga } from "../translations/ga";
+import { gl } from "../translations/gl";
+import { hr } from "../translations/hr";
+import { id } from "../translations/id";
+import { it } from "../translations/it";
+import { ja } from "../translations/ja";
+import { ko } from "../translations/ko";
+import { nl } from "../translations/nl";
+import { oc } from "../translations/oc";
+import { pl } from "../translations/pl";
+import { pt } from "../translations/pt";
+import { pt_BR } from "../translations/pt_BR";
+import { ru } from "../translations/ru";
+import { sv } from "../translations/sv";
+import { vi } from "../translations/vi";
+import { zh } from "../translations/zh";
+import { zh_Hant } from "../translations/zh_Hant";
 
 export const languages = [
   { resource: ar, code: "ar", name: "العربية" },
@@ -92,16 +92,30 @@ class LanguageDetector {
   }
 }
 
-i18next.use(LanguageDetector).init({
-  debug: false,
-  compatibilityJSON: "v3",
-  supportedLngs: languages.map(l => l.code),
-  nonExplicitSupportedLngs: true,
-  // load: 'languageOnly',
-  // initImmediate: false,
-  fallbackLng: "en",
-  resources,
-  interpolation: { format },
-});
+export class I18NextService {
+  #i18n: typeof i18next;
+  static #instance: I18NextService;
 
-export const i18n = i18next as i18nTyped;
+  private constructor() {
+    this.#i18n = i18next;
+    this.#i18n.use(LanguageDetector).init({
+      debug: false,
+      compatibilityJSON: "v3",
+      supportedLngs: languages.map(l => l.code),
+      nonExplicitSupportedLngs: true,
+      // load: 'languageOnly',
+      // initImmediate: false,
+      fallbackLng: "en",
+      resources,
+      interpolation: { format },
+    });
+  }
+
+  static get #Instance() {
+    return this.#instance ?? (this.#instance = new this());
+  }
+
+  public static get i18n() {
+    return this.#Instance.#i18n;
+  }
+}
index 61abc2ebff9bf8475649f3d15b1bd54d818f85f5..df4f00a8bb07b71514cc2e07a82e1c3f4ec6937e 100644 (file)
@@ -5,8 +5,8 @@ import IsomorphicCookie from "isomorphic-cookie";
 import jwt_decode from "jwt-decode";
 import { LoginResponse, MyUserInfo } from "lemmy-js-client";
 import { isHttps } from "../env";
-import { i18n } from "../i18next";
 import { toast } from "../toast";
+import { I18NextService } from "./I18NextService";
 
 interface Claims {
   sub: number;
@@ -32,7 +32,7 @@ export class UserService {
     const expires = new Date();
     expires.setDate(expires.getDate() + 365);
     if (res.jwt) {
-      toast(i18n.t("logged_in"));
+      toast(I18NextService.i18n.t("logged_in"));
       IsomorphicCookie.save("jwt", res.jwt, { expires, secure: isHttps() });
       this.#setJwtInfo();
     }
@@ -58,7 +58,7 @@ export class UserService {
       const msg = "No JWT cookie found";
       if (throwErr && isBrowser()) {
         console.error(msg);
-        toast(i18n.t("not_logged_in"), "danger");
+        toast(I18NextService.i18n.t("not_logged_in"), "danger");
       }
       return undefined;
       // throw msg;
index f63a56be7be61b763dc5962bf4fda5721dde372f..5856245ac08a02475956c97d287a72be6abded88 100644 (file)
@@ -1,2 +1,5 @@
+export { FirstLoadService } from "./FirstLoadService";
+export { HistoryService } from "./HistoryService";
 export { HttpService } from "./HttpService";
+export { I18NextService } from "./I18NextService";
 export { UserService } from "./UserService";
index b8ab0623d2a6f138362fb19b28534c20d7ffcc7a..bd9b8a44477b4c9dbd240aaf47124adeb704240d 100644 (file)
@@ -1,7 +1,7 @@
 import { isBrowser } from "@utils/browser";
 import { ThemeColor } from "@utils/types";
 import Toastify from "toastify-js";
-import { i18n } from "./i18next";
+import { I18NextService } from "./services";
 
 export function toast(text: string, background: ThemeColor = "success") {
   if (isBrowser()) {
@@ -18,13 +18,18 @@ export function toast(text: string, background: ThemeColor = "success") {
 
 export function pictrsDeleteToast(filename: string, deleteUrl: string) {
   if (isBrowser()) {
-    const clickToDeleteText = i18n.t("click_to_delete_picture", { filename });
-    const deletePictureText = i18n.t("picture_deleted", {
+    const clickToDeleteText = I18NextService.i18n.t("click_to_delete_picture", {
       filename,
     });
-    const failedDeletePictureText = i18n.t("failed_to_delete_picture", {
+    const deletePictureText = I18NextService.i18n.t("picture_deleted", {
       filename,
     });
+    const failedDeletePictureText = I18NextService.i18n.t(
+      "failed_to_delete_picture",
+      {
+        filename,
+      }
+    );
 
     const backgroundColor = `var(--bs-light)`;
 
index 0f2a2dfe7f00b9d8f2992d3ca91c6c4c80cd21dd..ac6d9cb617b1858f39cc51c89d652992d4f48e23 100644 (file)
@@ -1,11 +1,10 @@
 import { GetSiteResponse } from "lemmy-js-client";
-import { i18n } from "../../i18next";
 import { setupEmojiDataModel, setupMarkdown } from "../../markdown";
-import { UserService } from "../../services";
+import { I18NextService, UserService } from "../../services";
 
 export default function initializeSite(site?: GetSiteResponse) {
   UserService.Instance.myUserInfo = site?.my_user;
-  i18n.changeLanguage();
+  I18NextService.i18n.changeLanguage();
   if (site) {
     setupEmojiDataModel(site.custom_emojis ?? []);
   }
index 7042527211be9ab5564cb2e8ca8fe742a1865392..9faa1ca41cee3ffbd60ade880ce95c4d0b0f0775 100644 (file)
@@ -1,6 +1,5 @@
 import { BlockCommunityResponse, MyUserInfo } from "lemmy-js-client";
-import { i18n } from "../../i18next";
-import { UserService } from "../../services";
+import { I18NextService, UserService } from "../../services";
 import { toast } from "../../toast";
 
 export default function updateCommunityBlock(
@@ -13,12 +12,20 @@ export default function updateCommunityBlock(
         person: myUserInfo.local_user_view.person,
         community: data.community_view.community,
       });
-      toast(`${i18n.t("blocked")} ${data.community_view.community.name}`);
+      toast(
+        `${I18NextService.i18n.t("blocked")} ${
+          data.community_view.community.name
+        }`
+      );
     } else {
       myUserInfo.community_blocks = myUserInfo.community_blocks.filter(
         i => i.community.id !== data.community_view.community.id
       );
-      toast(`${i18n.t("unblocked")} ${data.community_view.community.name}`);
+      toast(
+        `${I18NextService.i18n.t("unblocked")} ${
+          data.community_view.community.name
+        }`
+      );
     }
   }
 }
index 3b5223bc03d68ae2cc6246d5791e0f2d60186ce1..cec72a333745936fefd991d9b230eedf398eae4d 100644 (file)
@@ -1,6 +1,5 @@
 import { BlockPersonResponse, MyUserInfo } from "lemmy-js-client";
-import { i18n } from "../../i18next";
-import { UserService } from "../../services";
+import { I18NextService, UserService } from "../../services";
 import { toast } from "../../toast";
 
 export default function updatePersonBlock(
@@ -13,12 +12,16 @@ export default function updatePersonBlock(
         person: myUserInfo.local_user_view.person,
         target: data.person_view.person,
       });
-      toast(`${i18n.t("blocked")} ${data.person_view.person.name}`);
+      toast(
+        `${I18NextService.i18n.t("blocked")} ${data.person_view.person.name}`
+      );
     } else {
       myUserInfo.person_blocks = myUserInfo.person_blocks.filter(
         i => i.target.id !== data.person_view.person.id
       );
-      toast(`${i18n.t("unblocked")} ${data.person_view.person.name}`);
+      toast(
+        `${I18NextService.i18n.t("unblocked")} ${data.person_view.person.name}`
+      );
     }
   }
 }