Skip to content

Commit aa04d45

Browse files
jicruz96Mephistic
andauthored
Search component translations (#1883)
* extract translate-able strings -- bill sort * rename billSearch.json to search.json and update refs * extract translate-able strings from TestimonyHit component * extract translate-able strings from search components * fix build error * extract translate-able strings from refinement components * fix/refactor useRefinements * remove unused hierarchical menu components * debug testimonyHit translations * remove unused CurrentCommitteeCard component and its associated stories * remove unused code from formatting.tsx * Revert "[1753] Replace custom routing with react-instantsearch-router-nextjs" * chore(transcriptions): Update firestore rules to allow read-only access to transcription paragraphs --------- Co-authored-by: Mephistic <[email protected]>
1 parent 86a21d1 commit aa04d45

17 files changed

+212
-272
lines changed

components/search/NoResults.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ const Container = styled.div`
1919
export const NoResults: React.FC<React.PropsWithChildren<unknown>> = ({
2020
children
2121
}) => {
22-
const { t } = useTranslation("common")
22+
const { t } = useTranslation("search")
2323
return (
2424
<Container>
25-
<Image src="/no-results.svg" alt={t("noResults")} />
26-
<div className="fs-3">Looks Pretty Empty Here</div>
25+
<Image src="/no-results.svg" alt={t("no_results")} />
26+
<div className="fs-3">{t("looks_pretty_empty_here")}</div>
2727
<div className="text-center">{children}</div>
2828
</Container>
2929
)

components/search/ResultCount.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useTranslation } from "next-i18next"
12
import { useStats } from "react-instantsearch"
23
import styled from "styled-components"
34

@@ -13,7 +14,11 @@ export function ResultCount(props: any) {
1314

1415
return (
1516
<ResultContainer {...props}>
16-
Showing {pageStart}-{pageEnd} of {nbHits} Results
17+
{useTranslation("search").t("result_count", {
18+
pageStart,
19+
pageEnd,
20+
nbHits
21+
})}
1722
</ResultContainer>
1823
)
1924
}

components/search/SearchErrorBoundary.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import React, { ReactNode } from "react"
22
import { Alert } from "react-bootstrap"
3+
import { withTranslation, WithTranslation } from "next-i18next"
34

4-
export class SearchErrorBoundary extends React.Component<{
5-
children?: ReactNode
6-
}> {
5+
class SearchErrorBoundaryBase extends React.Component<
6+
{ children?: ReactNode } & WithTranslation
7+
> {
78
state: { error: string | null } = { error: null }
89

910
promiseRejectionHandler = (event: PromiseRejectionEvent) => {
@@ -16,8 +17,7 @@ export class SearchErrorBoundary extends React.Component<{
1617
if (this.state.error) {
1718
return (
1819
<Alert variant="danger">
19-
Something went wrong. Please try again. Original message:{" "}
20-
{this.state.error}
20+
{this.props.t("search_error", { error: this.state.error })}
2121
</Alert>
2222
)
2323
}
@@ -44,3 +44,7 @@ export class SearchErrorBoundary extends React.Component<{
4444
)
4545
}
4646
}
47+
48+
export const SearchErrorBoundary = withTranslation("search")(
49+
SearchErrorBoundaryBase
50+
)

components/search/bills/BillSearch.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ const Layout: FC<
147147
const refinements = useBillRefinements()
148148
const status = useSearchStatus()
149149

150-
const { t } = useTranslation("billSearch")
150+
const { t } = useTranslation("search")
151151

152152
return (
153153
<SearchContainer>

components/search/bills/useBillHierarchicalMenu.tsx

Lines changed: 0 additions & 17 deletions
This file was deleted.
Lines changed: 30 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { generalCourts } from "functions/src/shared"
22
import { RefinementListItem } from "instantsearch.js/es/connectors/refinement-list/connectRefinementList"
3-
import { useCallback } from "react"
3+
import { useMemo } from "react"
44
import { useRefinements } from "../useRefinements"
5+
import { useTranslation } from "next-i18next"
56

67
// for legacy code purposes, things like:
78
//
@@ -17,58 +18,35 @@ import { useRefinements } from "../useRefinements"
1718
// searchablePlaceholder: "Legislative Session",
1819

1920
export const useBillRefinements = () => {
20-
const baseProps = { limit: 500, searchable: true }
21-
const propsList = [
22-
{
23-
transformItems: useCallback(
24-
(i: RefinementListItem[]) =>
25-
i
26-
.map(i => ({
27-
...i,
28-
label: generalCourts[i.value as any]?.Name ?? i.label
29-
}))
30-
.sort((a, b) => Number(b.value) - Number(a.value)),
31-
[]
32-
),
33-
attribute: "court",
34-
searchablePlaceholder: "Legislative Session",
35-
...baseProps
36-
},
37-
{
38-
attribute: "currentCommittee",
39-
...baseProps,
40-
searchablePlaceholder: "Current Committee"
41-
},
42-
{
43-
attribute: "city",
44-
searchablePlaceholder: "City",
45-
...baseProps
46-
},
47-
{
48-
attribute: "primarySponsor",
49-
...baseProps,
50-
searchablePlaceholder: "Primary Sponsor"
51-
},
52-
{
53-
attribute: "cosponsors",
54-
...baseProps,
55-
searchablePlaceholder: "Cosponsor"
56-
}
57-
]
58-
59-
const hierarchicalPropsList = [
60-
{
61-
attribute: "topics.lvl0",
62-
...baseProps
63-
},
64-
{
65-
attribute: "topics.lvl1",
66-
...baseProps
67-
}
68-
]
21+
const { t } = useTranslation("search")
6922

7023
return useRefinements({
71-
hierarchicalMenuProps: hierarchicalPropsList,
72-
refinementProps: propsList
24+
hierarchicalMenuProps: { attributes: ["topics.lvl0", "topics.lvl1"] },
25+
refinementProps: useMemo(
26+
() =>
27+
[
28+
{
29+
transformItems: (items: RefinementListItem[]) =>
30+
items
31+
.map(i => ({
32+
...i,
33+
label: generalCourts[parseInt(i.value, 10)]?.Name ?? i.label
34+
}))
35+
.sort((a, b) => Number(b.value) - Number(a.value)),
36+
37+
attribute: "court"
38+
},
39+
{ attribute: "currentCommittee" },
40+
{ attribute: "city" },
41+
{ attribute: "primarySponsor" },
42+
{ attribute: "cosponsors" }
43+
].map(props => ({
44+
limit: 500,
45+
searchable: true,
46+
searchablePlaceholder: t(`refinements.bill.${props.attribute}`),
47+
...props
48+
})),
49+
[t]
50+
)
7351
})
7452
}
Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,33 @@
11
import { useMemo, useRef } from "react"
22
import { SortByWithConfigurationItem } from "../SortBy"
3+
import { useTranslation } from "next-i18next"
34

45
export const useBillSort = () => {
56
const now = useRef(new Date().getTime())
7+
const { t } = useTranslation("search")
68

79
// refer to
810
// https://github.com/typesense/typesense-instantsearch-adapter#with-react-instantsearch
911
const items: SortByWithConfigurationItem[] = useMemo(
1012
() => [
1113
{
12-
label: "Sort by Most Recent Testimony",
14+
label: t("sort_by.most_recent_testimony"),
1315
value: "bills/sort/latestTestimonyAt:desc"
1416
},
1517
{
16-
label: "Sort by Relevance",
18+
label: t("sort_by.relevance"),
1719
value: "bills/sort/_text_match:desc,testimonyCount:desc"
1820
},
1921
{
20-
label: "Sort by Testimony Count",
22+
label: t("sort_by.testimony_count"),
2123
value: "bills/sort/testimonyCount:desc"
2224
},
2325
{
24-
label: "Sort by Cosponsor Count",
26+
label: t("sort_by.cosponsor_count"),
2527
value: "bills/sort/cosponsorCount:desc"
2628
},
2729
{
28-
label: "Sort by Next Hearing Date",
30+
label: t("sort_by.next_hearing_date"),
2931
value: "bills/sort/nextHearingAt:asc",
3032
configure: {
3133
numericRefinements: {
@@ -36,7 +38,7 @@ export const useBillSort = () => {
3638
}
3739
}
3840
],
39-
[]
41+
[t]
4042
)
4143
return items
4244
}

components/search/testimony/TestimonyHit.tsx

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Hit } from "instantsearch.js"
22
import Link from "next/link"
3-
import { useTranslation } from "next-i18next"
3+
import { Trans, useTranslation } from "next-i18next"
44
import { Image } from "react-bootstrap"
55
import { useMediaQuery } from "usehooks-ts"
66

@@ -25,8 +25,6 @@ export const TestimonyHit = ({ hit }: { hit: Hit<Testimony> }) => {
2525
}
2626

2727
const TestimonyResult = ({ hit }: { hit: Hit<Testimony> }) => {
28-
const { t } = useTranslation(["auth"])
29-
3028
const date = new Date(
3129
parseInt(hit.publishedAt.toString())
3230
).toLocaleDateString("en-US", {
@@ -37,12 +35,6 @@ const TestimonyResult = ({ hit }: { hit: Hit<Testimony> }) => {
3735
const { loading, error, result: bill } = useBill(hit.court, hit.billId)
3836
const committee = bill?.currentCommittee
3937
const isOrg = hit.authorRole === "organization"
40-
const writtenBy =
41-
isOrg || hit.public ? (
42-
<Link href={`/profile?id=${hit.authorUid}`}>{hit.fullName}</Link>
43-
) : (
44-
hit.fullName
45-
)
4638
const { user } = useAuth()
4739
const { followOrg } = useFlags()
4840
const isCurrentUser = user?.uid === hit.authorUid
@@ -67,12 +59,25 @@ const TestimonyResult = ({ hit }: { hit: Hit<Testimony> }) => {
6759
>
6860
<Image
6961
src={isOrg ? "/profile-org-icon.svg" : "/profile-individual-icon.svg"}
70-
alt={t("profileIcon")}
62+
alt={useTranslation("auth").t("profileIcon")}
7163
height="30px"
7264
width="30px"
7365
/>
7466
<span style={{ flexGrow: 1 }}>
75-
<b>Written by {writtenBy}</b>
67+
<b>
68+
<Trans
69+
ns="testimony"
70+
i18nKey="testimonyHit.writtenBy"
71+
values={{ author: hit.fullName }}
72+
components={[
73+
isOrg || hit.public ? (
74+
<Link href={`/profile?id=${hit.authorUid}`} />
75+
) : (
76+
<></>
77+
)
78+
]}
79+
/>
80+
</b>
7681
</span>
7782
{hit.public && !isCurrentUser && followOrg && user && (
7883
<FollowUserButton profileId={hit.authorUid} />
@@ -95,7 +100,11 @@ const TestimonyResult = ({ hit }: { hit: Hit<Testimony> }) => {
95100
<div style={{ display: "flex", alignItems: "center", gap: "15px" }}>
96101
{/* <Link href={maple.bill({ court: hit.court, id: hit.billId })}> */}
97102
{/* <a> */}
98-
<h2>Bill #{formatBillId(hit.billId)}</h2>
103+
<h2>
104+
{useTranslation("testimony").t("testimonyHit.bill", {
105+
billId: formatBillId(hit.billId)
106+
})}
107+
</h2>
99108
{/* </a> */}
100109
{/* </Link> */}
101110
{committee && (

0 commit comments

Comments
 (0)