diff --git a/deno.lock b/deno.lock index 672e1e1a8..ef3664f43 100644 --- a/deno.lock +++ b/deno.lock @@ -852,8 +852,8 @@ "@ardatan/relay-compiler@12.0.3_graphql@16.11.0-canary.pr.4364.2b4ffe237616247a733274dfdcb404c3d55d9f02": { "integrity": "sha512-mBDFOGvAoVlWaWqs3hm1AciGHSQE1rqFc/liZTyYz/Oek9yZdT5H26pH2zAFuEiTiBVPPyMuqf5VjOFPI2DGsQ==", "dependencies": [ - "@babel/generator@7.29.1", - "@babel/parser@7.29.2", + "@babel/generator", + "@babel/parser", "@babel/runtime", "chalk@4.1.2", "fb-watchman", @@ -1417,15 +1417,7 @@ "@babel/code-frame@7.27.1": { "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dependencies": [ - "@babel/helper-validator-identifier@7.28.5", - "js-tokens@4.0.0", - "picocolors" - ] - }, - "@babel/code-frame@7.29.0": { - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", - "dependencies": [ - "@babel/helper-validator-identifier@7.28.5", + "@babel/helper-validator-identifier", "js-tokens@4.0.0", "picocolors" ] @@ -1433,7 +1425,7 @@ "@babel/code-frame@7.29.7": { "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "dependencies": [ - "@babel/helper-validator-identifier@7.29.7", + "@babel/helper-validator-identifier", "js-tokens@4.0.0", "picocolors" ] @@ -1445,14 +1437,14 @@ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dependencies": [ "@babel/code-frame@7.29.7", - "@babel/generator@7.29.7", + "@babel/generator", "@babel/helper-compilation-targets", - "@babel/helper-module-transforms@7.29.7_@babel+core@7.29.7", + "@babel/helper-module-transforms", "@babel/helpers", - "@babel/parser@7.29.7", - "@babel/template@7.29.7", - "@babel/traverse@7.29.7", - "@babel/types@7.29.7", + "@babel/parser", + "@babel/template", + "@babel/traverse", + "@babel/types", "@jridgewell/remapping", "convert-source-map", "debug@4.4.3", @@ -1461,21 +1453,11 @@ "semver@6.3.1" ] }, - "@babel/generator@7.29.1": { - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", - "dependencies": [ - "@babel/parser@7.29.2", - "@babel/types@7.29.0", - "@jridgewell/gen-mapping", - "@jridgewell/trace-mapping", - "jsesc" - ] - }, "@babel/generator@7.29.7": { "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "dependencies": [ - "@babel/parser@7.29.7", - "@babel/types@7.29.7", + "@babel/parser", + "@babel/types", "@jridgewell/gen-mapping", "@jridgewell/trace-mapping", "jsesc" @@ -1484,14 +1466,14 @@ "@babel/helper-annotate-as-pure@7.27.3": { "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", "dependencies": [ - "@babel/types@7.29.0" + "@babel/types" ] }, "@babel/helper-compilation-targets@7.29.7": { "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "dependencies": [ "@babel/compat-data", - "@babel/helper-validator-option@7.29.7", + "@babel/helper-validator-option", "browserslist", "lru-cache@5.1.1", "semver@6.3.1" @@ -1505,49 +1487,31 @@ "@babel/helper-optimise-call-expression", "@babel/helper-replace-supers", "@babel/helper-skip-transparent-expression-wrappers", - "@babel/traverse@7.29.0", + "@babel/traverse", "semver@6.3.1" ] }, - "@babel/helper-globals@7.28.0": { - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==" - }, "@babel/helper-globals@7.29.7": { "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==" }, "@babel/helper-member-expression-to-functions@7.28.5": { "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", "dependencies": [ - "@babel/traverse@7.29.0", - "@babel/types@7.29.0" + "@babel/traverse", + "@babel/types" ] }, "@babel/helper-module-imports@7.18.6": { "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dependencies": [ - "@babel/types@7.29.0" - ] - }, - "@babel/helper-module-imports@7.28.6": { - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", - "dependencies": [ - "@babel/traverse@7.29.0", - "@babel/types@7.29.0" + "@babel/types" ] }, "@babel/helper-module-imports@7.29.7": { "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "dependencies": [ - "@babel/traverse@7.29.7", - "@babel/types@7.29.7" - ] - }, - "@babel/helper-module-transforms@7.28.6_@babel+core@7.28.3": { - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", - "dependencies": [ - "@babel/helper-module-imports@7.28.6", - "@babel/helper-validator-identifier@7.28.5", - "@babel/traverse@7.29.0" + "@babel/traverse", + "@babel/types" ] }, "@babel/helper-module-transforms@7.29.7_@babel+core@7.29.7": { @@ -1555,14 +1519,14 @@ "dependencies": [ "@babel/core", "@babel/helper-module-imports@7.29.7", - "@babel/helper-validator-identifier@7.29.7", - "@babel/traverse@7.29.7" + "@babel/helper-validator-identifier", + "@babel/traverse" ] }, "@babel/helper-optimise-call-expression@7.27.1": { "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", "dependencies": [ - "@babel/types@7.29.0" + "@babel/types" ] }, "@babel/helper-plugin-utils@7.28.6": { @@ -1573,52 +1537,36 @@ "dependencies": [ "@babel/helper-member-expression-to-functions", "@babel/helper-optimise-call-expression", - "@babel/traverse@7.29.0" + "@babel/traverse" ] }, "@babel/helper-skip-transparent-expression-wrappers@7.27.1": { "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", "dependencies": [ - "@babel/traverse@7.29.0", - "@babel/types@7.29.0" + "@babel/traverse", + "@babel/types" ] }, - "@babel/helper-string-parser@7.27.1": { - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==" - }, "@babel/helper-string-parser@7.29.7": { "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==" }, - "@babel/helper-validator-identifier@7.28.5": { - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==" - }, "@babel/helper-validator-identifier@7.29.7": { "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==" }, - "@babel/helper-validator-option@7.27.1": { - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==" - }, "@babel/helper-validator-option@7.29.7": { "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==" }, "@babel/helpers@7.29.7": { "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dependencies": [ - "@babel/template@7.29.7", - "@babel/types@7.29.7" + "@babel/template", + "@babel/types" ] }, - "@babel/parser@7.29.2": { - "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", - "dependencies": [ - "@babel/types@7.29.0" - ], - "bin": true - }, "@babel/parser@7.29.7": { "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "dependencies": [ - "@babel/types@7.29.7" + "@babel/types" ], "bin": true }, @@ -1644,7 +1592,7 @@ "@babel/plugin-transform-modules-commonjs@7.28.6_@babel+core@7.28.3": { "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", "dependencies": [ - "@babel/helper-module-transforms@7.28.6_@babel+core@7.28.3", + "@babel/helper-module-transforms", "@babel/helper-plugin-utils" ] }, @@ -1662,7 +1610,7 @@ "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==", "dependencies": [ "@babel/helper-plugin-utils", - "@babel/helper-validator-option@7.27.1", + "@babel/helper-validator-option", "@babel/plugin-syntax-jsx", "@babel/plugin-transform-modules-commonjs", "@babel/plugin-transform-typescript" @@ -1671,58 +1619,31 @@ "@babel/runtime@7.28.3": { "integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==" }, - "@babel/template@7.28.6": { - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", - "dependencies": [ - "@babel/code-frame@7.29.0", - "@babel/parser@7.29.2", - "@babel/types@7.29.0" - ] - }, "@babel/template@7.29.7": { "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "dependencies": [ "@babel/code-frame@7.29.7", - "@babel/parser@7.29.7", - "@babel/types@7.29.7" - ] - }, - "@babel/traverse@7.29.0": { - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", - "dependencies": [ - "@babel/code-frame@7.29.0", - "@babel/generator@7.29.1", - "@babel/helper-globals@7.28.0", - "@babel/parser@7.29.2", - "@babel/template@7.28.6", - "@babel/types@7.29.0", - "debug@4.4.3" + "@babel/parser", + "@babel/types" ] }, "@babel/traverse@7.29.7": { "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "dependencies": [ "@babel/code-frame@7.29.7", - "@babel/generator@7.29.7", - "@babel/helper-globals@7.29.7", - "@babel/parser@7.29.7", - "@babel/template@7.29.7", - "@babel/types@7.29.7", + "@babel/generator", + "@babel/helper-globals", + "@babel/parser", + "@babel/template", + "@babel/types", "debug@4.4.3" ] }, - "@babel/types@7.29.0": { - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dependencies": [ - "@babel/helper-string-parser@7.27.1", - "@babel/helper-validator-identifier@7.28.5" - ] - }, "@babel/types@7.29.7": { "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "dependencies": [ - "@babel/helper-string-parser@7.29.7", - "@babel/helper-validator-identifier@7.29.7" + "@babel/helper-string-parser", + "@babel/helper-validator-identifier" ] }, "@cloudflare/kv-asset-handler@0.4.2": { @@ -2616,9 +2537,9 @@ "@graphql-codegen/cli@5.0.7_@parcel+watcher@2.5.6_graphql@16.11.0-canary.pr.4364.2b4ffe237616247a733274dfdcb404c3d55d9f02": { "integrity": "sha512-h/sxYvSaWtxZxo8GtaA8SvcHTyViaaPd7dweF/hmRDpaQU1o3iU3EZxlcJ+oLTunU0tSMFsnrIXm/mhXxI11Cw==", "dependencies": [ - "@babel/generator@7.29.1", - "@babel/template@7.28.6", - "@babel/types@7.29.0", + "@babel/generator", + "@babel/template", + "@babel/types", "@graphql-codegen/client-preset", "@graphql-codegen/core", "@graphql-codegen/plugin-helpers", @@ -2663,7 +2584,7 @@ "integrity": "sha512-QpEsPSO9fnRxA6Z66AmBuGcwHjZ6dYSxYo5ycMlYgSPzAbyG8gn/kWljofjJfWqSY+T/lRn+r8IXTH14ml24vQ==", "dependencies": [ "@babel/helper-plugin-utils", - "@babel/template@7.28.6", + "@babel/template", "@graphql-codegen/add", "@graphql-codegen/gql-tag-operations", "@graphql-codegen/plugin-helpers", @@ -2933,10 +2854,10 @@ "integrity": "sha512-TJhELNvR1tmghXMi6HVKp/Swxbx1rcSp/zdkuJZT0DCM3vOY11FXY6NW3aoxumcuYDNN3jqXcCPKstYGFPi5GQ==", "dependencies": [ "@babel/core", - "@babel/parser@7.29.2", + "@babel/parser", "@babel/plugin-syntax-import-assertions", - "@babel/traverse@7.29.0", - "@babel/types@7.29.0", + "@babel/traverse", + "@babel/types", "@graphql-tools/utils", "graphql", "tslib@2.8.1" @@ -3539,7 +3460,7 @@ "integrity": "sha512-V15kARtjzWgLga/6LOTMMki5pv3F42m9BX8jdI1mBg4yCo1cS0B3szfoBqoveFs7x+nh0iuEPAKcM9lVdSYadw==", "dependencies": [ "@babel/core", - "@babel/types@7.29.0", + "@babel/types", "@lingui/conf", "@lingui/message-utils" ] @@ -3548,9 +3469,9 @@ "integrity": "sha512-OqtEPHFmgQlyroQMmpnda6QRnfAqlAYnRVZpZSX3rZpwwaHI1pD7T1EQoK8n7kin9TGhitc1J33wFom7o/+yyg==", "dependencies": [ "@babel/core", - "@babel/generator@7.29.1", - "@babel/parser@7.29.2", - "@babel/types@7.29.0", + "@babel/generator", + "@babel/parser", + "@babel/types", "@lingui/babel-plugin-extract-messages", "@lingui/babel-plugin-lingui-macro", "@lingui/conf", @@ -5831,8 +5752,8 @@ "integrity": "sha512-z56ATi3P07q8F5Io2I+RQrwjyWZtFZzpXN/J+8scf/gqrAW83LtgRkZFZjJaGH7i9WrHP+ep9F+ZiJ2gDHVBcw==", "dependencies": [ "@babel/core", - "@babel/traverse@7.29.0", - "@babel/types@7.29.0", + "@babel/traverse", + "@babel/types", "@solidjs/meta", "@tanstack/server-functions-plugin", "@types/babel__traverse", @@ -6074,8 +5995,8 @@ "dependencies": [ "@babel/code-frame@7.27.1", "@babel/core", - "@babel/traverse@7.29.0", - "@babel/types@7.29.0", + "@babel/traverse", + "@babel/types", "@tanstack/router-utils", "babel-dead-code-elimination", "pathe@2.0.3", @@ -6087,8 +6008,8 @@ "integrity": "sha512-WEp5D2gPxvlLDRXwD/fV7RXjYtqaqJNXKB/L6OyZEbT+9BG/Ib2d7oG9GSUZNNMGPGYAlhBUOi3xutySsk6rxA==", "dependencies": [ "@babel/core", - "@babel/generator@7.29.1", - "@babel/parser@7.29.2", + "@babel/generator", + "@babel/parser", "@babel/preset-typescript", "ansis", "diff", @@ -6103,9 +6024,9 @@ "@babel/core", "@babel/plugin-syntax-jsx", "@babel/plugin-syntax-typescript", - "@babel/template@7.28.6", - "@babel/traverse@7.29.0", - "@babel/types@7.29.0", + "@babel/template", + "@babel/traverse", + "@babel/types", "@tanstack/directive-functions-plugin", "babel-dead-code-elimination", "tiny-invariant" @@ -6114,7 +6035,6 @@ "@testing-library/dom@10.4.1": { "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", "dependencies": [ - "@babel/code-frame@7.29.0", "@babel/runtime", "@types/aria-query", "aria-query", @@ -6163,8 +6083,8 @@ "@types/babel__core@7.20.5": { "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dependencies": [ - "@babel/parser@7.29.2", - "@babel/types@7.29.0", + "@babel/parser", + "@babel/types", "@types/babel__generator", "@types/babel__template", "@types/babel__traverse" @@ -6173,20 +6093,20 @@ "@types/babel__generator@7.27.0": { "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "dependencies": [ - "@babel/types@7.29.0" + "@babel/types" ] }, "@types/babel__template@7.4.4": { "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dependencies": [ - "@babel/parser@7.29.2", - "@babel/types@7.29.0" + "@babel/parser", + "@babel/types" ] }, "@types/babel__traverse@7.28.0": { "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", "dependencies": [ - "@babel/types@7.29.0" + "@babel/types" ] }, "@types/braces@3.0.5": { @@ -6723,9 +6643,9 @@ "integrity": "sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig==", "dependencies": [ "@babel/core", - "@babel/parser@7.29.2", - "@babel/traverse@7.29.0", - "@babel/types@7.29.0" + "@babel/parser", + "@babel/traverse", + "@babel/types" ] }, "babel-helper-builder-react-jsx@6.26.0": { @@ -6741,7 +6661,7 @@ "dependencies": [ "@babel/helper-module-imports@7.18.6", "@babel/plugin-syntax-jsx", - "@babel/types@7.29.0", + "@babel/types", "html-entities", "parse5" ] @@ -9856,8 +9776,8 @@ "magicast@0.5.2": { "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", "dependencies": [ - "@babel/parser@7.29.2", - "@babel/types@7.29.0", + "@babel/parser", + "@babel/types", "source-map-js" ] }, @@ -10673,7 +10593,7 @@ "parse-json@5.2.0": { "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dependencies": [ - "@babel/code-frame@7.29.0", + "@babel/code-frame@7.29.7", "error-ex", "json-parse-even-better-errors", "lines-and-columns" @@ -11972,7 +11892,7 @@ "dependencies": [ "@babel/core", "@babel/plugin-syntax-typescript", - "@babel/types@7.29.0", + "@babel/types", "@solid-devtools/debugger", "@solid-devtools/shared", "solid-js", @@ -12007,9 +11927,9 @@ "solid-refresh@0.6.3_solid-js@1.9.10__seroval@1.3.2": { "integrity": "sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==", "dependencies": [ - "@babel/generator@7.29.1", - "@babel/helper-module-imports@7.28.6", - "@babel/types@7.29.0", + "@babel/generator", + "@babel/helper-module-imports@7.29.7", + "@babel/types", "solid-js" ] }, diff --git a/federation/actor.test.ts b/federation/actor.test.ts index d6a740a57..e9d0881a7 100644 --- a/federation/actor.test.ts +++ b/federation/actor.test.ts @@ -75,3 +75,38 @@ test("getAccountActor serves a suspended stub for banned accounts", async () => assert.equal(tempActor.name?.toString(), "AP Banned"); }); }); + +test("getAccountActor exposes account migration aliases", async () => { + await withRollback(async (tx) => { + const { account } = await insertAccountWithActor(tx, { + username: "apaliases", + name: "AP Aliases", + email: "apaliases@example.com", + }); + await tx.update(actorTable) + .set({ + aliases: [ + "https://old.example/users/apaliases", + "https://older.example/users/apaliases", + ], + }) + .where(eq(actorTable.accountId, account.id)); + const refreshed = await tx.query.accountTable.findFirst({ + where: { id: account.id }, + with: { + actor: true, + avatarMedium: true, + emails: true, + links: { orderBy: { index: "asc" } }, + }, + }); + assert.ok(refreshed != null); + + const actor = await getAccountActor(createFedCtx(tx), refreshed, []); + + assert.deepEqual(actor.aliasIds.map((alias) => alias.href), [ + "https://old.example/users/apaliases", + "https://older.example/users/apaliases", + ]); + }); +}); diff --git a/federation/person.ts b/federation/person.ts index b1ebb1dd3..7c151c8d0 100644 --- a/federation/person.ts +++ b/federation/person.ts @@ -49,6 +49,7 @@ export async function getAccountActor( followers: ctx.getFollowersUri(identifier), featured: ctx.getFeaturedUri(identifier), url: new URL(`/@${account.username}`, ctx.canonicalOrigin), + aliases: account.actor.aliases.map((alias) => new URL(alias)), }; if (isActorBanned(account.actor)) { return new Person({ diff --git a/graphql/account.test.ts b/graphql/account.test.ts index 156e10fa9..673cc621a 100644 --- a/graphql/account.test.ts +++ b/graphql/account.test.ts @@ -25,6 +25,7 @@ import { createTestDisk, createTestKv, insertAccountWithActor, + insertRemoteActor, makeGuestContext, makeUserContext, toPlainJson, @@ -52,6 +53,16 @@ const accountByUsernameQuery = parse(` } `); +const accountMigrationAliasesQuery = parse(` + query AccountMigrationAliases($username: String!) { + accountByUsername(username: $username) { + actor { + aliases + } + } + } +`); + const accountOgImageUrlQuery = parse(` query AccountOgImageUrl($username: String!) { accountByUsername(username: $username) { @@ -161,6 +172,56 @@ const deleteAccountMutation = parse(` } `); +const addAccountMigrationAliasMutation = parse(` + mutation AddAccountMigrationAlias($input: AddAccountMigrationAliasInput!) { + addAccountMigrationAlias(input: $input) { + __typename + ... on AddAccountMigrationAliasPayload { + account { + actor { + aliases + } + } + } + ... on NotAuthenticatedError { + notAuthenticated + } + ... on NotAuthorizedError { + notAuthorized + } + ... on InvalidInputError { + inputPath + } + } + } +`); + +const removeAccountMigrationAliasMutation = parse(` + mutation RemoveAccountMigrationAlias( + $input: RemoveAccountMigrationAliasInput! + ) { + removeAccountMigrationAlias(input: $input) { + __typename + ... on RemoveAccountMigrationAliasPayload { + account { + actor { + aliases + } + } + } + ... on NotAuthenticatedError { + notAuthenticated + } + ... on NotAuthorizedError { + notAuthorized + } + ... on InvalidInputError { + inputPath + } + } + } +`); + const smallPngDataUrl = "data:image/png;base64," + "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII="; @@ -1167,6 +1228,414 @@ test("updateAccount rejects usernames reserved by deleted accounts", async () => }); }); +test("Actor.aliases exposes account migration aliases", async () => { + await withRollback(async (tx) => { + const { account } = await insertAccountWithActor(tx, { + username: "aliasquery", + name: "Alias Query", + email: "aliasquery@example.com", + }); + await tx.update(actorTable) + .set({ aliases: ["https://old.example/users/aliasquery"] }) + .where(eq(actorTable.accountId, account.id)); + + const result = await execute({ + schema, + document: accountMigrationAliasesQuery, + variableValues: { username: "aliasquery" }, + contextValue: makeUserContext(tx, account), + }); + + assert.equal(result.errors, undefined); + assert.deepEqual(toPlainJson(result.data), { + accountByUsername: { + actor: { + aliases: ["https://old.example/users/aliasquery"], + }, + }, + }); + }); +}); + +test("addAccountMigrationAlias appends a resolved old actor once", async () => { + await withRollback(async (tx) => { + const { account } = await insertAccountWithActor(tx, { + username: "aliasowner", + name: "Alias Owner", + email: "aliasowner@example.com", + }); + await insertRemoteActor(tx, { + username: "oldalias", + name: "Old Alias", + host: "old.example", + iri: "https://old.example/users/oldalias", + url: "https://old.example/@oldalias", + }); + const fedCtx = createFedCtx(tx); + fedCtx.getActor = (identifier: string) => + Promise.resolve(new vocab.Person({ id: fedCtx.getActorUri(identifier) })); + const sentActivities: unknown[][] = []; + fedCtx.sendActivity = ((...args: unknown[]) => { + sentActivities.push(args); + return Promise.resolve(undefined); + }) as typeof fedCtx.sendActivity; + + for ( + const actor of [ + "@oldalias@old.example", + "oldalias@old.example", + "https://old.example/@oldalias", + ] + ) { + const result = await execute({ + schema, + document: addAccountMigrationAliasMutation, + variableValues: { + input: { + accountId: encodeGlobalID("Account", account.id), + actor, + }, + }, + contextValue: makeUserContext(tx, account, { fedCtx }), + onError: "NO_PROPAGATE", + }); + + assert.equal(result.errors, undefined); + assert.deepEqual(toPlainJson(result.data), { + addAccountMigrationAlias: { + __typename: "AddAccountMigrationAliasPayload", + account: { + actor: { + aliases: ["https://old.example/users/oldalias"], + }, + }, + }, + }); + } + + assert.equal(sentActivities.length, 3); + const actor = await tx.query.actorTable.findFirst({ + where: { accountId: account.id }, + }); + assert.deepEqual(actor?.aliases, ["https://old.example/users/oldalias"]); + }); +}); + +test("addAccountMigrationAlias resolves uncached handles by federation lookup", async () => { + await withRollback(async (tx) => { + const { account } = await insertAccountWithActor(tx, { + username: "aliaslookup", + name: "Alias Lookup", + email: "aliaslookup@example.com", + }); + const fedCtx = createFedCtx(tx); + fedCtx.getActor = (identifier: string) => + Promise.resolve(new vocab.Person({ id: fedCtx.getActorUri(identifier) })); + let lookedUp: string | undefined; + fedCtx.lookupObject = ((resource: string | URL) => { + lookedUp = resource.toString(); + return Promise.resolve( + new vocab.Person({ + id: new URL("https://lookup.example/users/oldlookup"), + preferredUsername: "oldlookup", + name: "Old Lookup", + inbox: new URL("https://lookup.example/users/oldlookup/inbox"), + endpoints: new vocab.Endpoints({ + sharedInbox: new URL("https://lookup.example/inbox"), + }), + url: new URL("https://lookup.example/@oldlookup"), + }), + ); + }) as typeof fedCtx.lookupObject; + + const result = await execute({ + schema, + document: addAccountMigrationAliasMutation, + variableValues: { + input: { + accountId: encodeGlobalID("Account", account.id), + actor: "oldlookup@lookup.example", + }, + }, + contextValue: makeUserContext(tx, account, { fedCtx }), + onError: "NO_PROPAGATE", + }); + + assert.equal(result.errors, undefined); + assert.equal(lookedUp, "oldlookup@lookup.example"); + assert.deepEqual(toPlainJson(result.data), { + addAccountMigrationAlias: { + __typename: "AddAccountMigrationAliasPayload", + account: { + actor: { + aliases: ["https://lookup.example/users/oldlookup"], + }, + }, + }, + }); + }); +}); + +test("addAccountMigrationAlias matches cached actors with mixed-case hosts", async () => { + await withRollback(async (tx) => { + const { account } = await insertAccountWithActor(tx, { + username: "aliascase", + name: "Alias Case", + email: "aliascase@example.com", + }); + await insertRemoteActor(tx, { + username: "oldcase", + name: "Old Case", + host: "old.example", + iri: "https://old.example/users/oldcase", + url: "https://old.example/@oldcase", + }); + const fedCtx = createFedCtx(tx); + fedCtx.getActor = (identifier: string) => + Promise.resolve(new vocab.Person({ id: fedCtx.getActorUri(identifier) })); + fedCtx.lookupObject = (() => { + throw new Error("cached mixed-case handles must not be looked up"); + }) as typeof fedCtx.lookupObject; + + const result = await execute({ + schema, + document: addAccountMigrationAliasMutation, + variableValues: { + input: { + accountId: encodeGlobalID("Account", account.id), + actor: "@oldcase@Old.Example", + }, + }, + contextValue: makeUserContext(tx, account, { fedCtx }), + onError: "NO_PROPAGATE", + }); + + assert.equal(result.errors, undefined); + assert.deepEqual(toPlainJson(result.data), { + addAccountMigrationAlias: { + __typename: "AddAccountMigrationAliasPayload", + account: { + actor: { + aliases: ["https://old.example/users/oldcase"], + }, + }, + }, + }); + }); +}); + +test("addAccountMigrationAlias does not resurrect aliases removed during lookup", async () => { + await withRollback(async (tx) => { + const { account } = await insertAccountWithActor(tx, { + username: "aliasrace", + name: "Alias Race", + email: "aliasrace@example.com", + }); + await tx.update(actorTable) + .set({ aliases: ["https://old.example/users/removed"] }) + .where(eq(actorTable.accountId, account.id)); + const fedCtx = createFedCtx(tx); + fedCtx.getActor = (identifier: string) => + Promise.resolve(new vocab.Person({ id: fedCtx.getActorUri(identifier) })); + fedCtx.lookupObject = (async (resource: string | URL) => { + assert.equal(resource.toString(), "fresh@localhost"); + await tx.update(actorTable) + .set({ aliases: [] }) + .where(eq(actorTable.accountId, account.id)); + return new vocab.Person({ + id: new URL("https://localhost/users/fresh"), + preferredUsername: "fresh", + name: "Fresh Alias", + inbox: new URL("https://localhost/users/fresh/inbox"), + endpoints: new vocab.Endpoints({ + sharedInbox: new URL("https://localhost/inbox"), + }), + url: new URL("https://localhost/@fresh"), + }); + }) as typeof fedCtx.lookupObject; + + const result = await execute({ + schema, + document: addAccountMigrationAliasMutation, + variableValues: { + input: { + accountId: encodeGlobalID("Account", account.id), + actor: "fresh@localhost", + }, + }, + contextValue: makeUserContext(tx, account, { fedCtx }), + onError: "NO_PROPAGATE", + }); + + assert.equal(result.errors, undefined); + assert.deepEqual(toPlainJson(result.data), { + addAccountMigrationAlias: { + __typename: "AddAccountMigrationAliasPayload", + account: { + actor: { + aliases: ["https://localhost/users/fresh"], + }, + }, + }, + }); + }); +}); + +test("addAccountMigrationAlias returns typed errors", async () => { + await withRollback(async (tx) => { + const owner = await insertAccountWithActor(tx, { + username: "aliasownererrors", + name: "Alias Owner Errors", + email: "aliasownererrors@example.com", + }); + const other = await insertAccountWithActor(tx, { + username: "aliasothererrors", + name: "Alias Other Errors", + email: "aliasothererrors@example.com", + }); + + const guest = await execute({ + schema, + document: addAccountMigrationAliasMutation, + variableValues: { + input: { + accountId: encodeGlobalID("Account", owner.account.id), + actor: "@old@remote.example", + }, + }, + contextValue: makeGuestContext(tx), + onError: "NO_PROPAGATE", + }); + assert.equal(guest.errors, undefined); + assert.equal( + (toPlainJson(guest.data) as { + addAccountMigrationAlias?: { __typename?: string }; + }).addAccountMigrationAlias?.__typename, + "NotAuthenticatedError", + ); + + const foreign = await execute({ + schema, + document: addAccountMigrationAliasMutation, + variableValues: { + input: { + accountId: encodeGlobalID("Account", other.account.id), + actor: "@old@remote.example", + }, + }, + contextValue: makeUserContext(tx, owner.account), + onError: "NO_PROPAGATE", + }); + assert.equal(foreign.errors, undefined); + assert.equal( + (toPlainJson(foreign.data) as { + addAccountMigrationAlias?: { __typename?: string }; + }).addAccountMigrationAlias?.__typename, + "NotAuthorizedError", + ); + + const invalid = await execute({ + schema, + document: addAccountMigrationAliasMutation, + variableValues: { + input: { + accountId: encodeGlobalID("Account", owner.account.id), + actor: "not a handle", + }, + }, + contextValue: makeUserContext(tx, owner.account), + onError: "NO_PROPAGATE", + }); + assert.equal(invalid.errors, undefined); + assert.deepEqual(toPlainJson(invalid.data), { + addAccountMigrationAlias: { + __typename: "InvalidInputError", + inputPath: "actor", + }, + }); + + const self = await execute({ + schema, + document: addAccountMigrationAliasMutation, + variableValues: { + input: { + accountId: encodeGlobalID("Account", owner.account.id), + actor: owner.actor.iri, + }, + }, + contextValue: makeUserContext(tx, owner.account), + onError: "NO_PROPAGATE", + }); + assert.equal(self.errors, undefined); + assert.deepEqual(toPlainJson(self.data), { + addAccountMigrationAlias: { + __typename: "InvalidInputError", + inputPath: "actor", + }, + }); + }); +}); + +test("removeAccountMigrationAlias removes one alias idempotently", async () => { + await withRollback(async (tx) => { + const { account } = await insertAccountWithActor(tx, { + username: "aliasremove", + name: "Alias Remove", + email: "aliasremove@example.com", + }); + await tx.update(actorTable) + .set({ + aliases: [ + "https://old.example/users/aliasremove", + "https://older.example/users/aliasremove", + ], + }) + .where(eq(actorTable.accountId, account.id)); + const fedCtx = createFedCtx(tx); + fedCtx.getActor = (identifier: string) => + Promise.resolve(new vocab.Person({ id: fedCtx.getActorUri(identifier) })); + const sentActivities: unknown[][] = []; + fedCtx.sendActivity = ((...args: unknown[]) => { + sentActivities.push(args); + return Promise.resolve(undefined); + }) as typeof fedCtx.sendActivity; + + for ( + const alias of [ + "https://old.example/users/aliasremove", + "https://old.example/users/aliasremove", + ] + ) { + const result = await execute({ + schema, + document: removeAccountMigrationAliasMutation, + variableValues: { + input: { + accountId: encodeGlobalID("Account", account.id), + alias, + }, + }, + contextValue: makeUserContext(tx, account, { fedCtx }), + onError: "NO_PROPAGATE", + }); + + assert.equal(result.errors, undefined); + assert.deepEqual(toPlainJson(result.data), { + removeAccountMigrationAlias: { + __typename: "RemoveAccountMigrationAliasPayload", + account: { + actor: { + aliases: ["https://older.example/users/aliasremove"], + }, + }, + }, + }); + } + + assert.equal(sentActivities.length, 2); + }); +}); + test("deleteAccount deletes the viewer account and session", async () => { await withRollback(async (tx) => { const { kv } = createTestKv(); diff --git a/graphql/account.ts b/graphql/account.ts index 60fabc3f3..8f73cc361 100644 --- a/graphql/account.ts +++ b/graphql/account.ts @@ -1,3 +1,4 @@ +import { isActor } from "@fedify/vocab"; import { getLogger } from "@logtape/logtape"; import { drizzleConnectionHelpers } from "@pothos/plugin-drizzle"; import { @@ -15,14 +16,16 @@ import { deleteAccount as deleteAccountModel, getAvatarUrl, isUsernameReserved, + sendAccountActorUpdate, updateAccount, } from "@hackerspub/models/account"; -import { syncActorFromAccount } from "@hackerspub/models/actor"; +import { persistActor, syncActorFromAccount } from "@hackerspub/models/actor"; import type { Locale } from "@hackerspub/models/i18n"; import { renderMarkup } from "@hackerspub/models/markup"; import { deleteSession } from "@hackerspub/models/session"; import { accountTable, + type Actor as ActorRow, actorTable, notificationTable, postTable, @@ -37,6 +40,7 @@ import { } from "./builder.ts"; import { InvalidInputError, NotAuthorizedError } from "./error.ts"; import { InvitationLink } from "./invitation-link.ts"; +import { lookupActorByUrl, parseHttpUrl } from "./lookup.ts"; import { Notification } from "./notification.ts"; import { putProfileOgImage } from "./og.ts"; import { ArticleDraft } from "./post.ts"; @@ -107,6 +111,130 @@ const sanctionActorRelation = { }, } as const; +function parseActorHandle(raw: string): { + handle: string; + username: string; + host: string; +} | null { + const trimmed = raw.trim().replace(/^@/, ""); + const split = trimmed.split("@"); + if (split.length !== 2) return null; + const username = split[0].trim(); + const host = split[1].trim().toLowerCase(); + if (username === "" || host === "") return null; + return { handle: `${username}@${host}`, username, host }; +} + +async function lookupActorByHandle( + ctx: UserContext, + raw: string, +): Promise { + const parsed = parseActorHandle(raw); + if (parsed == null) return null; + const existing = await ctx.db.query.actorTable.findFirst({ + where: { + username: parsed.username, + OR: [{ instanceHost: parsed.host }, { handleHost: parsed.host }], + }, + }); + if (existing != null) return existing; + if (ctx.account == null) return null; + + const documentLoader = await ctx.fedCtx.getDocumentLoader({ + identifier: ctx.account.id, + }); + let object; + try { + object = await ctx.fedCtx.lookupObject(parsed.handle, { documentLoader }); + } catch { + return null; + } + if (!isActor(object)) return null; + return (await persistActor(ctx.fedCtx, object, { documentLoader })) ?? null; +} + +async function lookupMigrationAliasActor( + ctx: UserContext, + raw: string, +): Promise { + const trimmed = raw.trim(); + if (trimmed === "") return null; + const url = parseHttpUrl(trimmed); + if (url != null) return await lookupActorByUrl(ctx, url); + return await lookupActorByHandle(ctx, trimmed); +} + +async function getAuthorizedMigrationAccount( + ctx: UserContext, + accountId: string, +) { + const session = await ctx.session; + if (session == null || ctx.account == null) { + throw new NotAuthenticatedError(); + } + if (!validateUuid(accountId)) throw new InvalidInputError("accountId"); + if (session.accountId !== accountId) throw new NotAuthorizedError(); + const account = await ctx.db.query.accountTable.findFirst({ + where: { id: accountId }, + with: { actor: true }, + }); + if (account?.actor == null) throw new InvalidInputError("accountId"); + return account; +} + +async function getUpdatedMigrationAccount( + ctx: UserContext, + accountId: Uuid, + updated: Date, +) { + await sendAccountActorUpdate(ctx.fedCtx, accountId, updated); + const account = await ctx.db.query.accountTable.findFirst({ + where: { id: accountId }, + }); + if (account == null) throw new InvalidInputError("accountId"); + return account; +} + +async function addAccountMigrationAlias( + ctx: UserContext, + accountId: Uuid, + alias: string, +) { + const rows = await ctx.db.update(actorTable) + .set({ + aliases: sql` + CASE + WHEN ${alias} = ANY(${actorTable.aliases}) + THEN ${actorTable.aliases} + ELSE array_append(${actorTable.aliases}, ${alias}) + END + `, + updated: sql`CURRENT_TIMESTAMP`, + }) + .where(eq(actorTable.accountId, accountId)) + .returning(); + const actor = rows[0]; + if (actor == null) throw new InvalidInputError("accountId"); + return await getUpdatedMigrationAccount(ctx, accountId, actor.updated); +} + +async function removeAccountMigrationAlias( + ctx: UserContext, + accountId: Uuid, + alias: string, +) { + const rows = await ctx.db.update(actorTable) + .set({ + aliases: sql`array_remove(${actorTable.aliases}, ${alias})`, + updated: sql`CURRENT_TIMESTAMP`, + }) + .where(eq(actorTable.accountId, accountId)) + .returning(); + const actor = rows[0]; + if (actor == null) throw new InvalidInputError("accountId"); + return await getUpdatedMigrationAccount(ctx, accountId, actor.updated); +} + export const Account = builder.drizzleNode("accountTable", { name: "Account", description: @@ -1234,6 +1362,124 @@ builder.relayMutationField( }, ); +builder.relayMutationField( + "addAccountMigrationAlias", + { + description: + "Add a previous account actor as an ActivityPub migration alias for " + + "the authenticated viewer's local account. The stored value is the " + + "resolved actor IRI, which is then advertised as `alsoKnownAs` on " + + "the local actor document so a later remote `Move` can be validated.", + inputFields: (t) => ({ + accountId: t.globalID({ + for: Account, + required: true, + description: + "The `Account` global id owned by the authenticated viewer. " + + "Passing another account id returns `NotAuthorizedError`.", + }), + actor: t.string({ + required: true, + description: + "Previous account to import from, written as `@user@host`, " + + "`user@host`, or an HTTP(S) actor/profile URL. The value is " + + "resolved before storage so aliases always contain actor IRIs.", + }), + }), + }, + { + errors: { + types: [NotAuthenticatedError, NotAuthorizedError, InvalidInputError], + }, + async resolve(_root, args, ctx) { + const account = await getAuthorizedMigrationAccount( + ctx, + args.input.accountId.id, + ); + const oldActor = await lookupMigrationAliasActor(ctx, args.input.actor); + if ( + oldActor == null || + oldActor.id === account.actor.id || + oldActor.accountId === account.id + ) { + throw new InvalidInputError("actor"); + } + return await addAccountMigrationAlias(ctx, account.id, oldActor.iri); + }, + }, + { + outputFields: (t) => ({ + account: t.field({ + type: Account, + description: + "The updated local account. Read `Account.actor.aliases` for " + + "the canonical set of previous actor IRIs now advertised as " + + "`alsoKnownAs`.", + resolve(result) { + return result; + }, + }), + }), + }, +); + +builder.relayMutationField( + "removeAccountMigrationAlias", + { + description: + "Remove one ActivityPub migration alias from the authenticated " + + "viewer's local account. Removing an alias only changes the new " + + "account's `alsoKnownAs` list; it does not send or retract a remote " + + "`Move` activity.", + inputFields: (t) => ({ + accountId: t.globalID({ + for: Account, + required: true, + description: + "The `Account` global id owned by the authenticated viewer. " + + "Passing another account id returns `NotAuthorizedError`.", + }), + alias: t.field({ + type: "URL", + required: true, + description: "The exact previous actor IRI to remove from " + + "`Account.actor.aliases`. Missing aliases are accepted so " + + "clients can retry safely.", + }), + }), + }, + { + errors: { + types: [NotAuthenticatedError, NotAuthorizedError, InvalidInputError], + }, + async resolve(_root, args, ctx) { + const account = await getAuthorizedMigrationAccount( + ctx, + args.input.accountId.id, + ); + return await removeAccountMigrationAlias( + ctx, + account.id, + args.input.alias.href, + ); + }, + }, + { + outputFields: (t) => ({ + account: t.field({ + type: Account, + description: + "The updated local account. Read `Account.actor.aliases` for " + + "the canonical set of previous actor IRIs now advertised as " + + "`alsoKnownAs`.", + resolve(result) { + return result; + }, + }), + }), + }, +); + builder.relayMutationField( "deleteAccount", { diff --git a/graphql/actor.ts b/graphql/actor.ts index 65719a507..4ec6f7b81 100644 --- a/graphql/actor.ts +++ b/graphql/actor.ts @@ -436,6 +436,20 @@ export const Actor = builder.drizzleNode("actorTable", { return actor.url ? new URL(actor.url) : null; }, }), + aliases: t.field({ + type: ["URL"], + description: + "ActivityPub aliases (`alsoKnownAs`) advertised by this actor. " + + "For local accounts, these are previous actor IRIs that remote " + + "servers use to validate Mastodon-style account migration `Move` " + + "activities.", + select: { + columns: { aliases: true }, + }, + resolve(actor) { + return actor.aliases.map((alias) => new URL(alias)); + }, + }), updated: t.expose("updated", { type: "DateTime" }), published: t.expose("published", { type: "DateTime", diff --git a/graphql/schema.graphql b/graphql/schema.graphql index e46a14e62..7f71837a9 100644 --- a/graphql/schema.graphql +++ b/graphql/schema.graphql @@ -317,6 +317,11 @@ type Actor implements Node { """ account: Account + """ + ActivityPub aliases (`alsoKnownAs`) advertised by this actor. For local accounts, these are previous actor IRIs that remote servers use to validate Mastodon-style account migration `Move` activities. + """ + aliases: [URL!]! + """ This actor's locally-authored `Article`-type posts, newest first. Only includes articles that have a local `articleSource` row; remote articles federated in from other instances are excluded. """ @@ -694,6 +699,32 @@ type ActorViewerInteractionsConnectionEdge { node: Post! } +""" +Add a previous account actor as an ActivityPub migration alias for the authenticated viewer's local account. The stored value is the resolved actor IRI, which is then advertised as `alsoKnownAs` on the local actor document so a later remote `Move` can be validated. +""" +input AddAccountMigrationAliasInput { + """ + The `Account` global id owned by the authenticated viewer. Passing another account id returns `NotAuthorizedError`. + """ + accountId: ID! + + """ + Previous account to import from, written as `@user@host`, `user@host`, or an HTTP(S) actor/profile URL. The value is resolved before storage so aliases always contain actor IRIs. + """ + actor: String! + clientMutationId: ID +} + +type AddAccountMigrationAliasPayload { + """ + The updated local account. Read `Account.actor.aliases` for the canonical set of previous actor IRIs now advertised as `alsoKnownAs`. + """ + account: Account! + clientMutationId: ID +} + +union AddAccountMigrationAliasResult = AddAccountMigrationAliasPayload | InvalidInputError | NotAuthenticatedError | NotAuthorizedError + union AddNewsExcludedPatternResult = InvalidInputError | NewsExcludedPattern | NotAuthenticatedError | NotAuthorizedError union AddNewsPreferredSharerResult = InvalidInputError | NewsPreferredSharer | NotAuthenticatedError | NotAuthorizedError @@ -2129,6 +2160,8 @@ type ModerationStatistics { } type Mutation { + addAccountMigrationAlias(input: AddAccountMigrationAliasInput!): AddAccountMigrationAliasResult! + """ Add a news feed exclusion pattern (a `URLPattern` string) and hide matching links from the feed list. Idempotent on the pattern string. Requires a moderator account. An invalid pattern raises `InvalidInputError`. """ @@ -2367,6 +2400,7 @@ type Mutation { Register or refresh a push notification target for the authenticated viewer. `APNS` and `FCM` require `token`; `WEB_PUSH` requires `endpoint`, `p256dh`, and `auth` from the browser `PushSubscription`. """ registerPushNotificationTarget(input: RegisterPushNotificationTargetInput!): RegisterPushNotificationTargetResult! + removeAccountMigrationAlias(input: RemoveAccountMigrationAliasInput!): RemoveAccountMigrationAliasResult! """ Remove an `Actor` from the authenticated viewer's followers. This deletes the follower relationship without blocking the actor; remote followers receive an ActivityPub `Reject` for the original `Follow`. @@ -4499,6 +4533,32 @@ type RelaySubscription implements Node { uuid: UUID! } +""" +Remove one ActivityPub migration alias from the authenticated viewer's local account. Removing an alias only changes the new account's `alsoKnownAs` list; it does not send or retract a remote `Move` activity. +""" +input RemoveAccountMigrationAliasInput { + """ + The `Account` global id owned by the authenticated viewer. Passing another account id returns `NotAuthorizedError`. + """ + accountId: ID! + + """ + The exact previous actor IRI to remove from `Account.actor.aliases`. Missing aliases are accepted so clients can retry safely. + """ + alias: URL! + clientMutationId: ID +} + +type RemoveAccountMigrationAliasPayload { + """ + The updated local account. Read `Account.actor.aliases` for the canonical set of previous actor IRIs now advertised as `alsoKnownAs`. + """ + account: Account! + clientMutationId: ID +} + +union RemoveAccountMigrationAliasResult = InvalidInputError | NotAuthenticatedError | NotAuthorizedError | RemoveAccountMigrationAliasPayload + """ Remove an `Actor` from the authenticated viewer's followers. This deletes the follower relationship without blocking the actor; remote followers receive an ActivityPub `Reject` for the original `Follow`. """ diff --git a/models/account.ts b/models/account.ts index 07a90259d..8a9d68876 100644 --- a/models/account.ts +++ b/models/account.ts @@ -671,24 +671,32 @@ export async function updateAccount( account.links, ); } + await sendAccountActorUpdate(fedCtx, result.id, result.updated); + return { ...result, links }; +} + +export async function sendAccountActorUpdate( + fedCtx: RequestContext, + accountId: Uuid, + updated: Date, +): Promise { await fedCtx.sendActivity( - { identifier: result.id }, + { identifier: accountId }, "followers", new vocab.Update({ id: new URL( - `#update/${result.updated.toISOString()}`, - fedCtx.getActorUri(result.id), + `#update/${updated.toISOString()}`, + fedCtx.getActorUri(accountId), ), - actor: fedCtx.getActorUri(result.id), + actor: fedCtx.getActorUri(accountId), to: vocab.PUBLIC_COLLECTION, - object: await fedCtx.getActor(result.id), + object: await fedCtx.getActor(accountId), }), { preferSharedInbox: true, excludeBaseUris: [new URL(fedCtx.canonicalOrigin)], }, ); - return { ...result, links }; } export async function updateAccountData( diff --git a/web-next/src/locales/en-US/messages.po b/web-next/src/locales/en-US/messages.po index b6bd33d0d..f0cbeb0c2 100644 --- a/web-next/src/locales/en-US/messages.po +++ b/web-next/src/locales/en-US/messages.po @@ -113,7 +113,7 @@ msgid "{0, plural, one {Load # more reactor} other {Load # more reactors}}" msgstr "{0, plural, one {Load # more reactor} other {Load # more reactors}}" #. placeholder {0}: props.count -#: src/components/AppSidebar.tsx:457 +#: src/components/AppSidebar.tsx:440 msgid "{0, plural, one {Notifications (# unread)} other {Notifications (# unread)}}" msgstr "{0, plural, one {Notifications (# unread)} other {Notifications (# unread)}}" @@ -320,8 +320,8 @@ msgid "{0}'s following" msgstr "{0}'s following" #. placeholder {0}: actor.rawName ?? actor.username -#: src/routes/(root)/[handle]/(profile)/interactions.tsx:103 -#: src/routes/(root)/[handle]/(profile)/interactions.tsx:107 +#: src/routes/(root)/[handle]/(profile)/interactions.tsx:100 +#: src/routes/(root)/[handle]/(profile)/interactions.tsx:104 msgid "{0}'s interactions" msgstr "{0}'s interactions" @@ -366,6 +366,10 @@ msgstr "{days} days" msgid "{HIGH_PRIORITY_REPORT_COUNT}+ reports" msgstr "{HIGH_PRIORITY_REPORT_COUNT}+ reports" +#: src/routes/(root)/[handle]/settings/account.tsx:387 +msgid "@old@example.com or actor URL" +msgstr "@old@example.com or actor URL" + #: src/routes/(root)/[handle]/[idOrYear]/[slug]/reactions.tsx:231 #: src/routes/(root)/[handle]/[noteId]/reactions.tsx:253 #~ msgid "+{0} more reactor(s) not shown" @@ -452,12 +456,12 @@ msgid "A user (profile) report." msgstr "A user (profile) report." #: src/components/admin/AdminAccountsTable.tsx:224 -#: src/components/AppSidebar.tsx:498 +#: src/components/AppSidebar.tsx:481 #: src/components/SettingsTabs.tsx:112 msgid "Account" msgstr "Account" -#: src/routes/(root)/[handle]/settings/account.tsx:174 +#: src/routes/(root)/[handle]/settings/account.tsx:492 msgid "Account deletion is unavailable" msgstr "Account deletion is unavailable" @@ -465,11 +469,15 @@ msgstr "Account deletion is unavailable" msgid "Account handle" msgstr "Account handle" +#: src/routes/(root)/[handle]/settings/account.tsx:185 +msgid "Account migration" +msgstr "Account migration" + #: src/routes/(root)/[handle]/settings/sanctions.tsx:94 msgid "Account permanently suspended" msgstr "Account permanently suspended" -#: src/routes/(root)/[handle]/settings/account.tsx:124 +#: src/routes/(root)/[handle]/settings/account.tsx:179 msgid "Account settings" msgstr "Account settings" @@ -503,6 +511,7 @@ msgstr "Active since" msgid "Actors currently under an active suspension or federation block. Expired suspensions drop off automatically." msgstr "Actors currently under an active suspension or federation block. Expired suspensions drop off automatically." +#: src/routes/(root)/[handle]/settings/account.tsx:407 #: src/routes/(root)/[handle]/settings/language.tsx:196 #: src/routes/(root)/admin/news.tsx:639 #: src/routes/(root)/admin/news.tsx:748 @@ -527,10 +536,15 @@ msgstr "Add option" msgid "Add poll" msgstr "Add poll" +#: src/routes/(root)/[handle]/settings/account.tsx:360 +msgid "Add the old account here. Hackers' Pub will publish it as another account that belongs to you." +msgstr "Add the old account here. Hackers' Pub will publish it as another account that belongs to you." + #: src/components/HashtagActionBar.tsx:258 msgid "Add to sidebar" msgstr "Add to sidebar" +#: src/routes/(root)/[handle]/settings/account.tsx:407 #: src/routes/(root)/admin/news.tsx:639 #: src/routes/(root)/admin/news.tsx:748 msgid "Adding…" @@ -540,10 +554,18 @@ msgstr "Adding…" msgid "Additional context (optional)" msgstr "Additional context (optional)" -#: src/components/AppSidebar.tsx:649 +#: src/components/AppSidebar.tsx:632 msgid "Admin" msgstr "Admin" +#: src/routes/(root)/[handle]/settings/account.tsx:187 +#~ msgid "Advertise previous accounts before starting the move from the old server." +#~ msgstr "Advertise previous accounts before starting the move from the old server." + +#: src/routes/(root)/[handle]/settings/account.tsx:366 +msgid "After the old server confirms the destination, it sends the Move activity and compatible servers can move followers here." +msgstr "After the old server confirms the destination, it sends the Move activity and compatible servers can move followers here." + #: src/routes/(root)/[handle]/bookmarks.tsx:136 #: src/routes/(root)/admin/moderation/appeals.tsx:157 #: src/routes/(root)/admin/moderation/index.tsx:123 @@ -749,7 +771,7 @@ msgstr "article-url-slug" msgid "Articles" msgstr "Articles" -#: src/components/AppSidebar.tsx:289 +#: src/components/AppSidebar.tsx:272 #: src/components/ProfileCard.tsx:197 msgid "Articles only" msgstr "Articles only" @@ -841,7 +863,7 @@ msgstr "Bold" msgid "Bookmark" msgstr "Bookmark" -#: src/components/AppSidebar.tsx:585 +#: src/components/AppSidebar.tsx:568 #: src/routes/(root)/[handle]/bookmarks.tsx:126 msgid "Bookmarks" msgstr "Bookmarks" @@ -907,7 +929,7 @@ msgstr "By {0}" #: src/components/RemoveFollowerButton.tsx:144 #: src/components/ReportDialog.tsx:224 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/edit.tsx:523 -#: src/routes/(root)/[handle]/settings/account.tsx:269 +#: src/routes/(root)/[handle]/settings/account.tsx:588 #: src/routes/(root)/[handle]/settings/index.tsx:408 #: src/routes/(root)/[handle]/settings/passkeys.tsx:522 #: src/routes/(root)/authorize_interaction.tsx:273 @@ -918,10 +940,15 @@ msgstr "Cancel" msgid "Cannot change the language because translations already exist" msgstr "Cannot change the language because translations already exist" -#: src/routes/(root)/[handle]/settings/account.tsx:191 +#: src/routes/(root)/[handle]/settings/account.tsx:509 msgid "Cannot delete this account" msgstr "Cannot delete this account" +#: src/routes/(root)/[handle]/settings/account.tsx:279 +#: src/routes/(root)/[handle]/settings/account.tsx:330 +msgid "Cannot update this account" +msgstr "Cannot update this account" + #: src/components/admin/ModerationSubTabs.tsx:28 msgid "Cases" msgstr "Cases" @@ -1001,7 +1028,7 @@ msgstr "Closed" msgid "Code" msgstr "Code" -#: src/components/AppSidebar.tsx:872 +#: src/components/AppSidebar.tsx:855 #: src/routes/(root)/coc.tsx:40 #: src/routes/(root)/sign/up/[token].tsx:458 msgid "Code of conduct" @@ -1016,7 +1043,7 @@ msgstr "Code of conduct: {0}" #~ msgid "Comments ({0})" #~ msgstr "Comments ({0})" -#: src/components/AppSidebar.tsx:709 +#: src/components/AppSidebar.tsx:692 #: src/components/FloatingComposeButton.tsx:61 msgid "Compose" msgstr "Compose" @@ -1051,6 +1078,16 @@ msgstr "Copied" msgid "Copy" msgstr "Copy" +#: src/routes/(root)/[handle]/settings/account.tsx:286 +#: src/routes/(root)/[handle]/settings/account.tsx:292 +#~ msgid "Could not add migration alias" +#~ msgstr "Could not add migration alias" + +#: src/routes/(root)/[handle]/settings/account.tsx:287 +#: src/routes/(root)/[handle]/settings/account.tsx:293 +msgid "Could not add previous account" +msgstr "Could not add previous account" + #: src/routes/(root)/[handle]/settings/invite.tsx:638 msgid "Could not copy the link to the clipboard." msgstr "Could not copy the link to the clipboard." @@ -1073,6 +1110,16 @@ msgstr "Could not record the action" msgid "Could not refresh this from its origin." msgstr "Could not refresh this from its origin." +#: src/routes/(root)/[handle]/settings/account.tsx:334 +#: src/routes/(root)/[handle]/settings/account.tsx:342 +#~ msgid "Could not remove migration alias" +#~ msgstr "Could not remove migration alias" + +#: src/routes/(root)/[handle]/settings/account.tsx:336 +#: src/routes/(root)/[handle]/settings/account.tsx:344 +msgid "Could not remove previous account" +msgstr "Could not remove previous account" + #: src/routes/(root)/admin/refresh.tsx:129 msgid "Could not resolve that as a remote object." msgstr "Could not resolve that as a remote object." @@ -1096,7 +1143,7 @@ msgstr "Could not submit the appeal" msgid "Could not vote on this poll" msgstr "Could not vote on this poll" -#: src/components/AppSidebar.tsx:754 +#: src/components/AppSidebar.tsx:737 #: src/components/FloatingComposeButton.tsx:123 msgid "Create article" msgstr "Create article" @@ -1105,7 +1152,7 @@ msgstr "Create article" msgid "Create invitation link" msgstr "Create invitation link" -#: src/components/AppSidebar.tsx:731 +#: src/components/AppSidebar.tsx:714 #: src/components/FloatingComposeButton.tsx:99 #: src/components/NoteComposeModal.tsx:78 #: src/components/NoteComposer.tsx:1873 @@ -1191,13 +1238,13 @@ msgstr "Default share privacy" msgid "Delete" msgstr "Delete" -#: src/routes/(root)/[handle]/settings/account.tsx:125 -#: src/routes/(root)/[handle]/settings/account.tsx:253 -#: src/routes/(root)/[handle]/settings/account.tsx:278 +#: src/routes/(root)/[handle]/settings/account.tsx:199 +#: src/routes/(root)/[handle]/settings/account.tsx:572 +#: src/routes/(root)/[handle]/settings/account.tsx:597 msgid "Delete account" msgstr "Delete account" -#: src/routes/(root)/[handle]/settings/account.tsx:261 +#: src/routes/(root)/[handle]/settings/account.tsx:580 msgid "Delete account permanently?" msgstr "Delete account permanently?" @@ -1215,7 +1262,7 @@ msgid "Delete post?" msgstr "Delete post?" #: src/components/article-composer/ArticleComposerActions.tsx:21 -#: src/routes/(root)/[handle]/settings/account.tsx:278 +#: src/routes/(root)/[handle]/settings/account.tsx:597 #: src/routes/(root)/[handle]/settings/invite.tsx:745 #: src/routes/(root)/admin/media.tsx:189 msgid "Deleting…" @@ -1360,10 +1407,22 @@ msgstr "Ended" msgid "Ends" msgstr "Ends" +#: src/routes/(root)/[handle]/settings/account.tsx:284 +#~ msgid "Enter a valid previous account handle or actor URL." +#~ msgstr "Enter a valid previous account handle or actor URL." + #: src/components/ArticleComposer.tsx:540 #~ msgid "Enter article title..." #~ msgstr "Enter article title..." +#: src/routes/(root)/[handle]/settings/account.tsx:394 +msgid "Enter the account you are moving from, for example @old@example.com." +msgstr "Enter the account you are moving from, for example @old@example.com." + +#: src/routes/(root)/[handle]/settings/account.tsx:285 +msgid "Enter the account you are moving from, such as @old@example.com or its actor URL." +msgstr "Enter the account you are moving from, such as @old@example.com or its actor URL." + #: src/routes/(root)/[handle]/invite/[id].tsx:284 msgid "Enter your email address below to get started." msgstr "Enter your email address below to get started." @@ -1496,8 +1555,9 @@ msgstr "Failed to copy" msgid "Failed to create invitation link" msgstr "Failed to create invitation link" -#: src/routes/(root)/[handle]/settings/account.tsx:198 -#: src/routes/(root)/[handle]/settings/account.tsx:209 +#: src/routes/(root)/[handle]/settings/account.tsx:477 +#: src/routes/(root)/[handle]/settings/account.tsx:516 +#: src/routes/(root)/[handle]/settings/account.tsx:527 msgid "Failed to delete account" msgstr "Failed to delete account" @@ -1740,7 +1800,7 @@ msgid "Failed to share post" msgstr "Failed to share post" #. placeholder {0}: error.message -#: src/components/AppSidebar.tsx:144 +#: src/components/AppSidebar.tsx:127 msgid "Failed to sign out: {0}" msgstr "Failed to sign out: {0}" @@ -1818,7 +1878,7 @@ msgstr "Failed to vote" msgid "Favor links shared by specific accounts. A preferred sharer's posts count toward the news feed even when the account is a bot (for example a feed that reposts Hacker News links), and the links it shares get a flat promotion bonus in the popular ranking. A penalty on a link overrides the promotion." msgstr "Favor links shared by specific accounts. A preferred sharer's posts count toward the news feed even when the account is a bot (for example a feed that reposts Hacker News links), and the links it shares get a flat promotion bonus in the popular ranking. A penalty on a link overrides the promotion." -#: src/components/AppSidebar.tsx:341 +#: src/components/AppSidebar.tsx:324 msgid "Fediverse" msgstr "Fediverse" @@ -1826,7 +1886,7 @@ msgstr "Fediverse" msgid "Fediverse handle" msgstr "Fediverse handle" -#: src/components/AppSidebar.tsx:220 +#: src/components/AppSidebar.tsx:203 msgid "Feed" msgstr "Feed" @@ -1893,7 +1953,7 @@ msgstr "Generating…" msgid "Get browser notifications" msgstr "Get browser notifications" -#: src/components/AppSidebar.tsx:912 +#: src/components/AppSidebar.tsx:895 msgid "GitHub repository" msgstr "GitHub repository" @@ -1931,8 +1991,8 @@ msgstr "Grants one extra invitation to the most active accounts (the top third b msgid "Graph" msgstr "Graph" -#: src/components/AppSidebar.tsx:307 -#: src/components/AppSidebar.tsx:429 +#: src/components/AppSidebar.tsx:290 +#: src/components/AppSidebar.tsx:412 #: src/routes/(root).tsx:196 #: src/routes/(root)/coc.tsx:40 #: src/routes/(root)/markdown.tsx:40 @@ -1949,6 +2009,22 @@ msgstr "Hackers' Pub home" msgid "Hackers' Pub is a place for software engineers to share their knowledge and experience with each other. It's also an ActivityPub-enabled social network, so you can follow your favorite hackers in the fediverse and get their latest posts in your feed." msgstr "Hackers' Pub is a place for software engineers to share their knowledge and experience with each other. It's also an ActivityPub-enabled social network, so you can follow your favorite hackers in the fediverse and get their latest posts in your feed." +#: src/routes/(root)/[handle]/settings/account.tsx:317 +#~ msgid "Hackers' Pub no longer publishes that account as an alias." +#~ msgstr "Hackers' Pub no longer publishes that account as an alias." + +#: src/routes/(root)/[handle]/settings/account.tsx:317 +msgid "Hackers' Pub no longer publishes that account as another account that belongs to you." +msgstr "Hackers' Pub no longer publishes that account as another account that belongs to you." + +#: src/routes/(root)/[handle]/settings/account.tsx:266 +msgid "Hackers' Pub now publishes the old account as another account that belongs to you." +msgstr "Hackers' Pub now publishes the old account as another account that belongs to you." + +#: src/routes/(root)/[handle]/settings/account.tsx:266 +#~ msgid "Hackers' Pub now publishes the old account as belonging to you." +#~ msgstr "Hackers' Pub now publishes the old account as belonging to you." + #: src/routes/(root)/admin/index.tsx:88 msgid "Hackers' Pub: Admin · Accounts" msgstr "Hackers' Pub: Admin · Accounts" @@ -2147,7 +2223,7 @@ msgstr "Invitation links" msgid "Invitation sent" msgstr "Invitation sent" -#: src/components/AppSidebar.tsx:864 +#: src/components/AppSidebar.tsx:847 #: src/routes/(root)/[handle]/settings/invite.tsx:910 #: src/routes/(root)/tree/graph.tsx:79 #: src/routes/(root)/tree/index.tsx:206 @@ -2163,7 +2239,7 @@ msgstr "Invitations" msgid "Invitations left" msgstr "Invitations left" -#: src/components/AppSidebar.tsx:608 +#: src/components/AppSidebar.tsx:591 #: src/components/SettingsTabs.tsx:72 #: src/routes/(root)/[handle]/settings/invite.tsx:311 msgid "Invite" @@ -2521,6 +2597,14 @@ msgstr "Mentioned only" msgid "Message to the user (optional)" msgstr "Message to the user (optional)" +#: src/routes/(root)/[handle]/settings/account.tsx:264 +#~ msgid "Migration alias added" +#~ msgstr "Migration alias added" + +#: src/routes/(root)/[handle]/settings/account.tsx:314 +#~ msgid "Migration alias removed" +#~ msgstr "Migration alias removed" + #: src/components/ReportDialog.tsx:192 msgid "Minimum {MIN_REASON_LENGTH} characters required." msgstr "Minimum {MIN_REASON_LENGTH} characters required." @@ -2649,7 +2733,7 @@ msgid "Newest" msgstr "Newest" #: src/components/AdminTabs.tsx:58 -#: src/components/AppSidebar.tsx:193 +#: src/components/AppSidebar.tsx:176 #: src/routes/(root)/admin/news.tsx:555 #: src/routes/(root)/news/index.tsx:48 msgid "News" @@ -2730,6 +2814,10 @@ msgstr "No invitations left" msgid "No matching object found" msgstr "No matching object found" +#: src/routes/(root)/[handle]/settings/account.tsx:397 +#~ msgid "No migration aliases yet." +#~ msgstr "No migration aliases yet." + #: src/components/ActorArticleList.tsx:93 msgid "No notes articles" msgstr "No notes articles" @@ -2772,6 +2860,10 @@ msgstr "No preferred sharers yet." msgid "No previews" msgstr "No previews" +#: src/routes/(root)/[handle]/settings/account.tsx:416 +msgid "No previous accounts added yet." +msgstr "No previous accounts added yet." + #: src/routes/(root)/admin/moderation/statistics.tsx:223 msgid "No provisions have been cited yet." msgstr "No provisions have been cited yet." @@ -2888,8 +2980,8 @@ msgstr "Notification permission was not granted." msgid "Notification preview privacy" msgstr "Notification preview privacy" -#: src/components/AppSidebar.tsx:464 -#: src/components/AppSidebar.tsx:465 +#: src/components/AppSidebar.tsx:447 +#: src/components/AppSidebar.tsx:448 #: src/routes/(root).tsx:214 #: src/routes/(root).tsx:215 msgid "Notifications" @@ -2908,6 +3000,14 @@ msgstr "Notifications are blocked in your browser settings." msgid "Number of invitations" msgstr "Number of invitations" +#: src/routes/(root)/[handle]/settings/account.tsx:381 +msgid "Old account" +msgstr "Old account" + +#: src/routes/(root)/[handle]/settings/account.tsx:363 +msgid "On the old server, open account migration settings and set this Hackers' Pub account as the new account." +msgstr "On the old server, open account migration settings and set this Hackers' Pub account as the new account." + #: src/components/RefreshFromOriginItem.tsx:79 #: src/routes/(root)/admin/refresh.tsx:136 msgid "Only moderators can refresh remote objects." @@ -3006,7 +3106,7 @@ msgstr "Pending review" msgid "People you might want to follow" msgstr "People you might want to follow" -#: src/routes/(root)/[handle]/settings/account.tsx:126 +#: src/routes/(root)/[handle]/settings/account.tsx:201 msgid "Permanently delete your account and sign out of this session." msgstr "Permanently delete your account and sign out of this session." @@ -3052,7 +3152,17 @@ msgstr "Please enter a title for your article." msgid "Please enter your Fediverse handle." msgstr "Please enter your Fediverse handle." -#: src/routes/(root)/[handle]/settings/account.tsx:184 +#: src/routes/(root)/[handle]/settings/account.tsx:273 +#: src/routes/(root)/[handle]/settings/account.tsx:324 +msgid "Please sign in again before changing account migration settings." +msgstr "Please sign in again before changing account migration settings." + +#: src/routes/(root)/[handle]/settings/account.tsx:273 +#: src/routes/(root)/[handle]/settings/account.tsx:322 +#~ msgid "Please sign in again before changing migration aliases." +#~ msgstr "Please sign in again before changing migration aliases." + +#: src/routes/(root)/[handle]/settings/account.tsx:502 msgid "Please sign in again before deleting your account." msgstr "Please sign in again before deleting your account." @@ -3172,12 +3282,28 @@ msgstr "Preferred sharer removed." msgid "Preferred sharers" msgstr "Preferred sharers" +#: src/routes/(root)/[handle]/settings/account.tsx:187 +msgid "Prepare this account as the destination for a Mastodon-style move." +msgstr "Prepare this account as the destination for a Mastodon-style move." + #: src/components/article-composer/ArticleComposerForm.tsx:111 #: src/components/MarkdownEditor.tsx:164 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/edit.tsx:427 msgid "Preview" msgstr "Preview" +#: src/routes/(root)/[handle]/settings/account.tsx:362 +#~ msgid "Previous account" +#~ msgstr "Previous account" + +#: src/routes/(root)/[handle]/settings/account.tsx:264 +msgid "Previous account added" +msgstr "Previous account added" + +#: src/routes/(root)/[handle]/settings/account.tsx:315 +msgid "Previous account removed" +msgstr "Previous account removed" + #: src/components/ImageLightbox.tsx:80 msgid "Previous image" msgstr "Previous image" @@ -3190,7 +3316,7 @@ msgstr "Prior violations" msgid "Priority" msgstr "Priority" -#: src/components/AppSidebar.tsx:879 +#: src/components/AppSidebar.tsx:862 #: src/routes/(root)/privacy.tsx:40 msgid "Privacy policy" msgstr "Privacy policy" @@ -3344,7 +3470,7 @@ msgstr "Receive new notifications immediately, even when this tab is closed." msgid "Receive notifications immediately through this browser, even when this tab is closed." msgstr "Receive notifications immediately through this browser, even when this tab is closed." -#: src/components/AppSidebar.tsx:790 +#: src/components/AppSidebar.tsx:773 msgid "Recent drafts" msgstr "Recent drafts" @@ -3451,6 +3577,7 @@ msgid "Remote follow" msgstr "Remote follow" #: src/components/LanguageList.tsx:225 +#: src/routes/(root)/[handle]/settings/account.tsx:437 #: src/routes/(root)/admin/news.tsx:669 #: src/routes/(root)/admin/news.tsx:805 msgid "Remove" @@ -3461,6 +3588,10 @@ msgstr "Remove" msgid "Remove {0}" msgstr "Remove {0}" +#: src/routes/(root)/[handle]/settings/account.tsx:433 +msgid "Remove {alias}" +msgstr "Remove {alias}" + #: src/components/BookmarkButton.tsx:150 #: src/components/BookmarkButton.tsx:151 msgid "Remove bookmark" @@ -3508,6 +3639,10 @@ msgstr "Remove quote" msgid "Removes stored media that are old enough and no longer attached to an avatar, note, article draft, or article." msgstr "Removes stored media that are old enough and no longer attached to an avatar, note, article draft, or article." +#: src/routes/(root)/[handle]/settings/account.tsx:437 +msgid "Removing…" +msgstr "Removing…" + #: src/components/article-composer/ArticleComposerForm.tsx:134 #: src/components/MarkdownEditor.tsx:181 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/edit.tsx:453 @@ -3672,7 +3807,7 @@ msgid "Saving…" msgstr "Saving…" #: src/components/admin/AdminAccountsTable.tsx:202 -#: src/components/AppSidebar.tsx:363 +#: src/components/AppSidebar.tsx:346 #: src/components/SearchForm.tsx:65 #: src/components/SearchForm.tsx:80 #: src/routes/(root)/admin/moderation/index.tsx:192 @@ -3746,7 +3881,7 @@ msgstr "Separate tags with spaces. Tags help readers discover your article." msgid "Set your personal preferences." msgstr "Set your personal preferences." -#: src/components/AppSidebar.tsx:639 +#: src/components/AppSidebar.tsx:622 msgid "Settings" msgstr "Settings" @@ -3827,12 +3962,14 @@ msgstr "Shown to the reported user under the moderation team's identity." msgid "Shown to the user" msgstr "Shown to the user" -#: src/components/AppSidebar.tsx:540 +#: src/components/AppSidebar.tsx:523 #: src/routes/(root)/sign/index.tsx:419 msgid "Sign in" msgstr "Sign in" -#: src/routes/(root)/[handle]/settings/account.tsx:183 +#: src/routes/(root)/[handle]/settings/account.tsx:272 +#: src/routes/(root)/[handle]/settings/account.tsx:323 +#: src/routes/(root)/[handle]/settings/account.tsx:501 msgid "Sign in required" msgstr "Sign in required" @@ -3852,7 +3989,7 @@ msgstr "Sign in to vote" msgid "Sign in with passkey" msgstr "Sign in with passkey" -#: src/components/AppSidebar.tsx:851 +#: src/components/AppSidebar.tsx:834 msgid "Sign out" msgstr "Sign out" @@ -4094,8 +4231,9 @@ msgstr "The default privacy setting for your shares." msgid "The default quote permission for your notes." msgstr "The default quote permission for your notes." -#: src/routes/(root)/[handle]/settings/account.tsx:200 -#: src/routes/(root)/[handle]/settings/account.tsx:211 +#: src/routes/(root)/[handle]/settings/account.tsx:479 +#: src/routes/(root)/[handle]/settings/account.tsx:518 +#: src/routes/(root)/[handle]/settings/account.tsx:529 msgid "The deletion request could not be completed. Please try again." msgstr "The deletion request could not be completed. Please try again." @@ -4140,6 +4278,15 @@ msgstr "The invitation link has been deleted successfully." msgid "The link to this story is added to your post automatically." msgstr "The link to this story is added to your post automatically." +#: src/routes/(root)/[handle]/settings/account.tsx:293 +#~ msgid "The migration alias could not be added. Please try again." +#~ msgstr "The migration alias could not be added. Please try again." + +#: src/routes/(root)/[handle]/settings/account.tsx:335 +#: src/routes/(root)/[handle]/settings/account.tsx:343 +#~ msgid "The migration alias could not be removed. Please try again." +#~ msgstr "The migration alias could not be removed. Please try again." + #: src/components/AppealDialog.tsx:103 msgid "The moderation team will review your appeal and notify you." msgstr "The moderation team will review your appeal and notify you." @@ -4152,6 +4299,15 @@ msgstr "The page you're looking for doesn't exist or has been moved." msgid "The passkey has been successfully revoked." msgstr "The passkey has been successfully revoked." +#: src/routes/(root)/[handle]/settings/account.tsx:294 +msgid "The previous account could not be added. Please try again." +msgstr "The previous account could not be added. Please try again." + +#: src/routes/(root)/[handle]/settings/account.tsx:337 +#: src/routes/(root)/[handle]/settings/account.tsx:345 +msgid "The previous account could not be removed. Please try again." +msgstr "The previous account could not be removed. Please try again." + #: src/components/article-composer/ArticleComposerPublishFields.tsx:60 msgid "The primary language of your article, used for accessibility and discovery." msgstr "The primary language of your article, used for accessibility and discovery." @@ -4171,7 +4327,7 @@ msgstr "The sign-up link is invalid. Please make sure you're using the correct l #. placeholder {0}: "GITHUB_REPOSITORY" #. placeholder {1}: "AGPL-3.0" -#: src/components/AppSidebar.tsx:903 +#: src/components/AppSidebar.tsx:886 msgid "The source code of this website is available on {0} under the {1} license." msgstr "The source code of this website is available on {0} under the {1} license." @@ -4196,7 +4352,7 @@ msgstr "The Web Push public key is invalid." msgid "There are no moderation actions on your account." msgstr "There are no moderation actions on your account." -#: src/routes/(root)/[handle]/settings/account.tsx:176 +#: src/routes/(root)/[handle]/settings/account.tsx:494 msgid "This account cannot be deleted right now. Please contact the instance administrators." msgstr "This account cannot be deleted right now. Please contact the instance administrators." @@ -4216,7 +4372,7 @@ msgstr "This account is suspended." msgid "This action cannot be undone. This will permanently delete this post." msgstr "This action cannot be undone. This will permanently delete this post." -#: src/routes/(root)/[handle]/settings/account.tsx:223 +#: src/routes/(root)/[handle]/settings/account.tsx:541 msgid "This action is permanent." msgstr "This action is permanent." @@ -4225,7 +4381,7 @@ msgstr "This action is permanent." msgid "This browser does not support Web Push." msgstr "This browser does not support Web Push." -#: src/routes/(root)/[handle]/settings/account.tsx:264 +#: src/routes/(root)/[handle]/settings/account.tsx:583 msgid "This cannot be undone. Your account will be deleted and you will be signed out." msgstr "This cannot be undone. Your account will be deleted and you will be signed out." @@ -4268,6 +4424,10 @@ msgstr "This is a remote actor with no local notification or appeal. A warning i msgid "This is too long (maximum {MAX_REASON_LENGTH} characters)." msgstr "This is too long (maximum {MAX_REASON_LENGTH} characters)." +#: src/routes/(root)/[handle]/settings/account.tsx:356 +msgid "This page only prepares the Hackers' Pub side of the move. The move still starts from your old server." +msgstr "This page only prepares the Hackers' Pub side of the move. The move still starts from your old server." + #: src/components/QuoteTargetPlaceholder.tsx:36 msgid "This post quoted another post, but the quote is not currently authorized." msgstr "This post quoted another post, but the quote is not currently authorized." @@ -4312,7 +4472,7 @@ msgstr "This usually takes about a minute. The page will update automatically wh msgid "This will be part of the article URL." msgstr "This will be part of the article URL." -#: src/components/AppSidebar.tsx:167 +#: src/components/AppSidebar.tsx:150 msgid "Timeline" msgstr "Timeline" @@ -4361,9 +4521,9 @@ msgstr "Translating to {name}…" msgid "Translating…" msgstr "Translating…" -#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:379 -#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:402 -#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:411 +#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:391 +#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:414 +#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:423 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/index.tsx:615 msgid "Translation request failed" msgstr "Translation request failed" @@ -4387,7 +4547,7 @@ msgid "Try again" msgstr "Try again" #. placeholder {0}: props.username -#: src/routes/(root)/[handle]/settings/account.tsx:241 +#: src/routes/(root)/[handle]/settings/account.tsx:560 msgid "Type {0} to confirm account deletion." msgstr "Type {0} to confirm account deletion." @@ -4476,10 +4636,14 @@ msgstr "URL" msgid "URL pattern" msgstr "URL pattern" -#: src/components/AppSidebar.tsx:504 +#: src/components/AppSidebar.tsx:487 msgid "Use old UI" msgstr "Use old UI" +#: src/routes/(root)/[handle]/settings/account.tsx:375 +#~ msgid "Use the old account's handle or actor URL." +#~ msgstr "Use the old account's handle or actor URL." + #: src/components/ProfileActionMenu.tsx:320 msgid "User blocked" msgstr "User blocked" @@ -4502,7 +4666,7 @@ msgstr "User unblocked" msgid "User unmuted" msgstr "User unmuted" -#: src/routes/(root)/[handle]/settings/account.tsx:234 +#: src/routes/(root)/[handle]/settings/account.tsx:552 #: src/routes/(root)/[handle]/settings/index.tsx:423 #: src/routes/(root)/sign/up/[token].tsx:331 msgid "Username" @@ -4542,7 +4706,7 @@ msgstr "Verified that this link is owned by {0} {1}" msgid "Verifying your invitation…" msgstr "Verifying your invitation…" -#: src/components/AppSidebar.tsx:814 +#: src/components/AppSidebar.tsx:797 msgid "View all drafts →" msgstr "View all drafts →" @@ -4681,7 +4845,7 @@ msgstr "Withdraw decision" msgid "Withdrawn" msgstr "Withdrawn" -#: src/components/AppSidebar.tsx:263 +#: src/components/AppSidebar.tsx:246 msgid "Without shares" msgstr "Without shares" @@ -4744,7 +4908,12 @@ msgstr "You can attach up to {MAX_MEDIA} images" msgid "You can change it only once, and the old username will become available to others." msgstr "You can change it only once, and the old username will become available to others." -#: src/routes/(root)/[handle]/settings/account.tsx:192 +#: src/routes/(root)/[handle]/settings/account.tsx:280 +#: src/routes/(root)/[handle]/settings/account.tsx:329 +#~ msgid "You can change migration aliases only for your own account." +#~ msgstr "You can change migration aliases only for your own account." + +#: src/routes/(root)/[handle]/settings/account.tsx:510 msgid "You can delete only your own account." msgstr "You can delete only your own account." @@ -4773,6 +4942,11 @@ msgstr "You can only view your own bookmarks" msgid "You can only view your own drafts" msgstr "You can only view your own drafts" +#: src/routes/(root)/[handle]/settings/account.tsx:280 +#: src/routes/(root)/[handle]/settings/account.tsx:331 +msgid "You can prepare migration only for your own account." +msgstr "You can prepare migration only for your own account." + #: src/routes/(root)/[handle]/settings/passkeys.tsx:405 msgid "You don't have any passkeys registered yet." msgstr "You don't have any passkeys registered yet." @@ -4860,6 +5034,14 @@ msgstr "You've been invited to Hackers' Pub" msgid "Your account is suspended, so you can't post right now. See your sanctions for details and how to appeal." msgstr "Your account is suspended, so you can't post right now. See your sanctions for details and how to appeal." +#: src/routes/(root)/[handle]/settings/account.tsx:266 +#~ msgid "Your actor document now includes the previous account." +#~ msgstr "Your actor document now includes the previous account." + +#: src/routes/(root)/[handle]/settings/account.tsx:315 +#~ msgid "Your actor document was updated." +#~ msgstr "Your actor document was updated." + #: src/components/ModerationNotificationList.tsx:119 msgid "Your appeal was reviewed." msgstr "Your appeal was reviewed." @@ -4913,7 +5095,7 @@ msgstr "Your preferred languages have been updated." msgid "Your profile settings have been updated successfully." msgstr "Your profile settings have been updated successfully." -#: src/routes/(root)/[handle]/settings/account.tsx:226 +#: src/routes/(root)/[handle]/settings/account.tsx:544 msgid "Your profile, posts, drafts, follows, settings, and login credentials will be removed. Your current username will remain reserved." msgstr "Your profile, posts, drafts, follows, settings, and login credentials will be removed. Your current username will remain reserved." diff --git a/web-next/src/locales/ja-JP/messages.po b/web-next/src/locales/ja-JP/messages.po index 88cce9e91..69463b95f 100644 --- a/web-next/src/locales/ja-JP/messages.po +++ b/web-next/src/locales/ja-JP/messages.po @@ -113,7 +113,7 @@ msgid "{0, plural, one {Load # more reactor} other {Load # more reactors}}" msgstr "{0, plural, one {リアクター #件をもっと読み込む} other {リアクター #件をもっと読み込む}}" #. placeholder {0}: props.count -#: src/components/AppSidebar.tsx:457 +#: src/components/AppSidebar.tsx:440 msgid "{0, plural, one {Notifications (# unread)} other {Notifications (# unread)}}" msgstr "{0, plural, other {通知(未読#件)}}" @@ -320,8 +320,8 @@ msgid "{0}'s following" msgstr "{0}さんのフォロー中" #. placeholder {0}: actor.rawName ?? actor.username -#: src/routes/(root)/[handle]/(profile)/interactions.tsx:103 -#: src/routes/(root)/[handle]/(profile)/interactions.tsx:107 +#: src/routes/(root)/[handle]/(profile)/interactions.tsx:100 +#: src/routes/(root)/[handle]/(profile)/interactions.tsx:104 msgid "{0}'s interactions" msgstr "{0}さんとのやり取り" @@ -366,6 +366,10 @@ msgstr "{days}日間" msgid "{HIGH_PRIORITY_REPORT_COUNT}+ reports" msgstr "通報 {HIGH_PRIORITY_REPORT_COUNT}件以上" +#: src/routes/(root)/[handle]/settings/account.tsx:387 +msgid "@old@example.com or actor URL" +msgstr "@old@example.comまたはアクターURL" + #: src/routes/(root)/[handle]/[idOrYear]/[slug]/reactions.tsx:231 #: src/routes/(root)/[handle]/[noteId]/reactions.tsx:253 #~ msgid "+{0} more reactor(s) not shown" @@ -452,12 +456,12 @@ msgid "A user (profile) report." msgstr "ユーザー(プロフィール)の通報です。" #: src/components/admin/AdminAccountsTable.tsx:224 -#: src/components/AppSidebar.tsx:498 +#: src/components/AppSidebar.tsx:481 #: src/components/SettingsTabs.tsx:112 msgid "Account" msgstr "アカウント" -#: src/routes/(root)/[handle]/settings/account.tsx:174 +#: src/routes/(root)/[handle]/settings/account.tsx:492 msgid "Account deletion is unavailable" msgstr "アカウント削除は利用できません" @@ -465,11 +469,15 @@ msgstr "アカウント削除は利用できません" msgid "Account handle" msgstr "アカウントのハンドル" +#: src/routes/(root)/[handle]/settings/account.tsx:185 +msgid "Account migration" +msgstr "アカウント移行" + #: src/routes/(root)/[handle]/settings/sanctions.tsx:94 msgid "Account permanently suspended" msgstr "アカウントを永久停止" -#: src/routes/(root)/[handle]/settings/account.tsx:124 +#: src/routes/(root)/[handle]/settings/account.tsx:179 msgid "Account settings" msgstr "アカウント設定" @@ -503,6 +511,7 @@ msgstr "有効化日時:" msgid "Actors currently under an active suspension or federation block. Expired suspensions drop off automatically." msgstr "現在停止または連合ブロック中のアクターです。期限切れの停止は自動的に除外されます。" +#: src/routes/(root)/[handle]/settings/account.tsx:407 #: src/routes/(root)/[handle]/settings/language.tsx:196 #: src/routes/(root)/admin/news.tsx:639 #: src/routes/(root)/admin/news.tsx:748 @@ -527,10 +536,15 @@ msgstr "選択肢を追加" msgid "Add poll" msgstr "アンケートを追加" +#: src/routes/(root)/[handle]/settings/account.tsx:360 +msgid "Add the old account here. Hackers' Pub will publish it as another account that belongs to you." +msgstr "古いアカウントをここに追加してください。Hackers' Pubは、そのアカウントをあなたの別アカウントとして公開します。" + #: src/components/HashtagActionBar.tsx:258 msgid "Add to sidebar" msgstr "サイドバーに追加" +#: src/routes/(root)/[handle]/settings/account.tsx:407 #: src/routes/(root)/admin/news.tsx:639 #: src/routes/(root)/admin/news.tsx:748 msgid "Adding…" @@ -540,10 +554,18 @@ msgstr "追加中…" msgid "Additional context (optional)" msgstr "補足説明(任意)" -#: src/components/AppSidebar.tsx:649 +#: src/components/AppSidebar.tsx:632 msgid "Admin" msgstr "管理" +#: src/routes/(root)/[handle]/settings/account.tsx:187 +#~ msgid "Advertise previous accounts before starting the move from the old server." +#~ msgstr "古いサーバーから移行を開始する前に、以前のアカウントを公開します。" + +#: src/routes/(root)/[handle]/settings/account.tsx:366 +msgid "After the old server confirms the destination, it sends the Move activity and compatible servers can move followers here." +msgstr "古いサーバーが移行先を確認すると、Moveアクティビティを送信し、対応しているサーバーはフォロワーをこちらへ移行できます。" + #: src/routes/(root)/[handle]/bookmarks.tsx:136 #: src/routes/(root)/admin/moderation/appeals.tsx:157 #: src/routes/(root)/admin/moderation/index.tsx:123 @@ -749,7 +771,7 @@ msgstr "記事URLスラッグ" msgid "Articles" msgstr "記事" -#: src/components/AppSidebar.tsx:289 +#: src/components/AppSidebar.tsx:272 #: src/components/ProfileCard.tsx:197 msgid "Articles only" msgstr "記事のみ" @@ -841,7 +863,7 @@ msgstr "太字" msgid "Bookmark" msgstr "ブックマーク" -#: src/components/AppSidebar.tsx:585 +#: src/components/AppSidebar.tsx:568 #: src/routes/(root)/[handle]/bookmarks.tsx:126 msgid "Bookmarks" msgstr "ブックマーク" @@ -907,7 +929,7 @@ msgstr "{0}さんによる記事" #: src/components/RemoveFollowerButton.tsx:144 #: src/components/ReportDialog.tsx:224 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/edit.tsx:523 -#: src/routes/(root)/[handle]/settings/account.tsx:269 +#: src/routes/(root)/[handle]/settings/account.tsx:588 #: src/routes/(root)/[handle]/settings/index.tsx:408 #: src/routes/(root)/[handle]/settings/passkeys.tsx:522 #: src/routes/(root)/authorize_interaction.tsx:273 @@ -918,10 +940,15 @@ msgstr "キャンセル" msgid "Cannot change the language because translations already exist" msgstr "翻訳が既に存在するため、言語を変更できません" -#: src/routes/(root)/[handle]/settings/account.tsx:191 +#: src/routes/(root)/[handle]/settings/account.tsx:509 msgid "Cannot delete this account" msgstr "このアカウントは削除できません" +#: src/routes/(root)/[handle]/settings/account.tsx:279 +#: src/routes/(root)/[handle]/settings/account.tsx:330 +msgid "Cannot update this account" +msgstr "このアカウントを更新できません" + #: src/components/admin/ModerationSubTabs.tsx:28 msgid "Cases" msgstr "ケース" @@ -1001,7 +1028,7 @@ msgstr "終了" msgid "Code" msgstr "コード" -#: src/components/AppSidebar.tsx:872 +#: src/components/AppSidebar.tsx:855 #: src/routes/(root)/coc.tsx:40 #: src/routes/(root)/sign/up/[token].tsx:458 msgid "Code of conduct" @@ -1016,7 +1043,7 @@ msgstr "行動規範:{0}" #~ msgid "Comments ({0})" #~ msgstr "コメント({0})" -#: src/components/AppSidebar.tsx:709 +#: src/components/AppSidebar.tsx:692 #: src/components/FloatingComposeButton.tsx:61 msgid "Compose" msgstr "作成" @@ -1051,6 +1078,16 @@ msgstr "コピーしました" msgid "Copy" msgstr "コピー" +#: src/routes/(root)/[handle]/settings/account.tsx:286 +#: src/routes/(root)/[handle]/settings/account.tsx:292 +#~ msgid "Could not add migration alias" +#~ msgstr "移行エイリアスを追加できませんでした" + +#: src/routes/(root)/[handle]/settings/account.tsx:287 +#: src/routes/(root)/[handle]/settings/account.tsx:293 +msgid "Could not add previous account" +msgstr "古いアカウントを追加できませんでした" + #: src/routes/(root)/[handle]/settings/invite.tsx:638 msgid "Could not copy the link to the clipboard." msgstr "クリップボードにリンクをコピーできませんでした。" @@ -1073,6 +1110,16 @@ msgstr "対応を記録できませんでした" msgid "Could not refresh this from its origin." msgstr "この項目を配信元から再取得できませんでした。" +#: src/routes/(root)/[handle]/settings/account.tsx:334 +#: src/routes/(root)/[handle]/settings/account.tsx:342 +#~ msgid "Could not remove migration alias" +#~ msgstr "移行エイリアスを削除できませんでした" + +#: src/routes/(root)/[handle]/settings/account.tsx:336 +#: src/routes/(root)/[handle]/settings/account.tsx:344 +msgid "Could not remove previous account" +msgstr "古いアカウントを削除できませんでした" + #: src/routes/(root)/admin/refresh.tsx:129 msgid "Could not resolve that as a remote object." msgstr "リモートオブジェクトとして解決できませんでした。" @@ -1096,7 +1143,7 @@ msgstr "異議申し立てを送信できませんでした" msgid "Could not vote on this poll" msgstr "このアンケートに投票できませんでした" -#: src/components/AppSidebar.tsx:754 +#: src/components/AppSidebar.tsx:737 #: src/components/FloatingComposeButton.tsx:123 msgid "Create article" msgstr "記事を作成" @@ -1105,7 +1152,7 @@ msgstr "記事を作成" msgid "Create invitation link" msgstr "招待リンクを作成" -#: src/components/AppSidebar.tsx:731 +#: src/components/AppSidebar.tsx:714 #: src/components/FloatingComposeButton.tsx:99 #: src/components/NoteComposeModal.tsx:78 #: src/components/NoteComposer.tsx:1873 @@ -1191,13 +1238,13 @@ msgstr "共有のデフォルト公開範囲" msgid "Delete" msgstr "削除" -#: src/routes/(root)/[handle]/settings/account.tsx:125 -#: src/routes/(root)/[handle]/settings/account.tsx:253 -#: src/routes/(root)/[handle]/settings/account.tsx:278 +#: src/routes/(root)/[handle]/settings/account.tsx:199 +#: src/routes/(root)/[handle]/settings/account.tsx:572 +#: src/routes/(root)/[handle]/settings/account.tsx:597 msgid "Delete account" msgstr "アカウントを削除" -#: src/routes/(root)/[handle]/settings/account.tsx:261 +#: src/routes/(root)/[handle]/settings/account.tsx:580 msgid "Delete account permanently?" msgstr "アカウントを完全に削除しますか?" @@ -1215,7 +1262,7 @@ msgid "Delete post?" msgstr "コンテンツを削除しますか?" #: src/components/article-composer/ArticleComposerActions.tsx:21 -#: src/routes/(root)/[handle]/settings/account.tsx:278 +#: src/routes/(root)/[handle]/settings/account.tsx:597 #: src/routes/(root)/[handle]/settings/invite.tsx:745 #: src/routes/(root)/admin/media.tsx:189 msgid "Deleting…" @@ -1360,6 +1407,18 @@ msgstr "終了" msgid "Ends" msgstr "終了予定" +#: src/routes/(root)/[handle]/settings/account.tsx:284 +#~ msgid "Enter a valid previous account handle or actor URL." +#~ msgstr "有効な以前のアカウントのハンドルまたはアクターURLを入力してください。" + +#: src/routes/(root)/[handle]/settings/account.tsx:394 +msgid "Enter the account you are moving from, for example @old@example.com." +msgstr "移行元のアカウントを入力してください。例:@old@example.com。" + +#: src/routes/(root)/[handle]/settings/account.tsx:285 +msgid "Enter the account you are moving from, such as @old@example.com or its actor URL." +msgstr "移行元のアカウントを入力してください。@old@example.comやアクターURLを使用できます。" + #: src/routes/(root)/[handle]/invite/[id].tsx:284 msgid "Enter your email address below to get started." msgstr "以下にメールアドレスを入力して始めましょう。" @@ -1492,8 +1551,9 @@ msgstr "コピーに失敗しました" msgid "Failed to create invitation link" msgstr "招待リンクの作成に失敗しました" -#: src/routes/(root)/[handle]/settings/account.tsx:198 -#: src/routes/(root)/[handle]/settings/account.tsx:209 +#: src/routes/(root)/[handle]/settings/account.tsx:477 +#: src/routes/(root)/[handle]/settings/account.tsx:516 +#: src/routes/(root)/[handle]/settings/account.tsx:527 msgid "Failed to delete account" msgstr "アカウントを削除できませんでした" @@ -1736,7 +1796,7 @@ msgid "Failed to share post" msgstr "コンテンツの共有に失敗しました" #. placeholder {0}: error.message -#: src/components/AppSidebar.tsx:144 +#: src/components/AppSidebar.tsx:127 msgid "Failed to sign out: {0}" msgstr "ログアウトに失敗:{0}" @@ -1814,7 +1874,7 @@ msgstr "投票に失敗しました" msgid "Favor links shared by specific accounts. A preferred sharer's posts count toward the news feed even when the account is a bot (for example a feed that reposts Hacker News links), and the links it shares get a flat promotion bonus in the popular ranking. A penalty on a link overrides the promotion." msgstr "特定のアカウントが共有したリンクを優先します。優先共有者のコンテンツは、そのアカウントがボットであっても(例: Hacker Newsのリンクを再共有するフィード)ニュースフィードに集計され、そのアカウントが共有したリンクは人気ランキングで一定の加点を得ます。リンクにペナルティが付くと、優先よりもペナルティが優先されます。" -#: src/components/AppSidebar.tsx:341 +#: src/components/AppSidebar.tsx:324 msgid "Fediverse" msgstr "フェディバース" @@ -1822,7 +1882,7 @@ msgstr "フェディバース" msgid "Fediverse handle" msgstr "フェディバースのハンドル" -#: src/components/AppSidebar.tsx:220 +#: src/components/AppSidebar.tsx:203 msgid "Feed" msgstr "フィード" @@ -1889,7 +1949,7 @@ msgstr "生成中…" msgid "Get browser notifications" msgstr "ブラウザー通知を受け取る" -#: src/components/AppSidebar.tsx:912 +#: src/components/AppSidebar.tsx:895 msgid "GitHub repository" msgstr "GitHubリポジトリ" @@ -1927,8 +1987,8 @@ msgstr "前回の再付与カットオフ以降、最も活発なアカウント msgid "Graph" msgstr "グラフ" -#: src/components/AppSidebar.tsx:307 -#: src/components/AppSidebar.tsx:429 +#: src/components/AppSidebar.tsx:290 +#: src/components/AppSidebar.tsx:412 #: src/routes/(root).tsx:196 #: src/routes/(root)/coc.tsx:40 #: src/routes/(root)/markdown.tsx:40 @@ -1945,6 +2005,22 @@ msgstr "Hackers' Pubホーム" msgid "Hackers' Pub is a place for software engineers to share their knowledge and experience with each other. It's also an ActivityPub-enabled social network, so you can follow your favorite hackers in the fediverse and get their latest posts in your feed." msgstr "Hackers' Pubは、ソフトウェアエンジニアが知識と経験を共有する場所です。また、ActivityPubに対応したソーシャルネットワークでもあり、フェディバース(fediverse)で気に入ったハッカーをフォローして、最新のコンテンツをフィードで受け取ることができます。" +#: src/routes/(root)/[handle]/settings/account.tsx:317 +#~ msgid "Hackers' Pub no longer publishes that account as an alias." +#~ msgstr "Hackers' Pubは、そのアカウントをエイリアスとして公開しなくなりました。" + +#: src/routes/(root)/[handle]/settings/account.tsx:317 +msgid "Hackers' Pub no longer publishes that account as another account that belongs to you." +msgstr "Hackers' Pubは、そのアカウントをあなたの別アカウントとして公開しなくなりました。" + +#: src/routes/(root)/[handle]/settings/account.tsx:266 +msgid "Hackers' Pub now publishes the old account as another account that belongs to you." +msgstr "Hackers' Pubは、古いアカウントをあなたの別アカウントとして公開するようになりました。" + +#: src/routes/(root)/[handle]/settings/account.tsx:266 +#~ msgid "Hackers' Pub now publishes the old account as belonging to you." +#~ msgstr "Hackers' Pubは、古いアカウントをあなたのものとして公開するようになりました。" + #: src/routes/(root)/admin/index.tsx:88 msgid "Hackers' Pub: Admin · Accounts" msgstr "Hackers' Pub:管理 · アカウント" @@ -2143,7 +2219,7 @@ msgstr "招待リンク" msgid "Invitation sent" msgstr "招待状を送信しました" -#: src/components/AppSidebar.tsx:864 +#: src/components/AppSidebar.tsx:847 #: src/routes/(root)/[handle]/settings/invite.tsx:910 #: src/routes/(root)/tree/graph.tsx:79 #: src/routes/(root)/tree/index.tsx:206 @@ -2159,7 +2235,7 @@ msgstr "招待" msgid "Invitations left" msgstr "残り招待数" -#: src/components/AppSidebar.tsx:608 +#: src/components/AppSidebar.tsx:591 #: src/components/SettingsTabs.tsx:72 #: src/routes/(root)/[handle]/settings/invite.tsx:311 msgid "Invite" @@ -2517,6 +2593,14 @@ msgstr "メンションされたユーザーのみ" msgid "Message to the user (optional)" msgstr "ユーザーへのメッセージ(任意)" +#: src/routes/(root)/[handle]/settings/account.tsx:264 +#~ msgid "Migration alias added" +#~ msgstr "移行エイリアスを追加しました" + +#: src/routes/(root)/[handle]/settings/account.tsx:314 +#~ msgid "Migration alias removed" +#~ msgstr "移行エイリアスを削除しました" + #: src/components/ReportDialog.tsx:192 msgid "Minimum {MIN_REASON_LENGTH} characters required." msgstr "{MIN_REASON_LENGTH}文字以上入力してください。" @@ -2645,7 +2729,7 @@ msgid "Newest" msgstr "最新" #: src/components/AdminTabs.tsx:58 -#: src/components/AppSidebar.tsx:193 +#: src/components/AppSidebar.tsx:176 #: src/routes/(root)/admin/news.tsx:555 #: src/routes/(root)/news/index.tsx:48 msgid "News" @@ -2726,6 +2810,10 @@ msgstr "招待状が残っていません" msgid "No matching object found" msgstr "一致するオブジェクトが見つかりません" +#: src/routes/(root)/[handle]/settings/account.tsx:397 +#~ msgid "No migration aliases yet." +#~ msgstr "移行エイリアスはまだありません。" + #: src/components/ActorArticleList.tsx:93 msgid "No notes articles" msgstr "記事はありません" @@ -2768,6 +2856,10 @@ msgstr "まだ優先共有者がありません。" msgid "No previews" msgstr "プレビューなし" +#: src/routes/(root)/[handle]/settings/account.tsx:416 +msgid "No previous accounts added yet." +msgstr "古いアカウントはまだ追加されていません。" + #: src/routes/(root)/admin/moderation/statistics.tsx:223 msgid "No provisions have been cited yet." msgstr "まだ挙げられた条項はありません。" @@ -2884,8 +2976,8 @@ msgstr "通知の権限が許可されませんでした。" msgid "Notification preview privacy" msgstr "通知プレビューのプライバシー" -#: src/components/AppSidebar.tsx:464 -#: src/components/AppSidebar.tsx:465 +#: src/components/AppSidebar.tsx:447 +#: src/components/AppSidebar.tsx:448 #: src/routes/(root).tsx:214 #: src/routes/(root).tsx:215 msgid "Notifications" @@ -2904,6 +2996,14 @@ msgstr "ブラウザー設定で通知がブロックされています。" msgid "Number of invitations" msgstr "招待数" +#: src/routes/(root)/[handle]/settings/account.tsx:381 +msgid "Old account" +msgstr "古いアカウント" + +#: src/routes/(root)/[handle]/settings/account.tsx:363 +msgid "On the old server, open account migration settings and set this Hackers' Pub account as the new account." +msgstr "古いサーバーでアカウント移行設定を開き、このHackers' Pubアカウントを新しいアカウントに設定してください。" + #: src/components/RefreshFromOriginItem.tsx:79 #: src/routes/(root)/admin/refresh.tsx:136 msgid "Only moderators can refresh remote objects." @@ -3002,7 +3102,7 @@ msgstr "審査待ち" msgid "People you might want to follow" msgstr "フォローのおすすめ" -#: src/routes/(root)/[handle]/settings/account.tsx:126 +#: src/routes/(root)/[handle]/settings/account.tsx:201 msgid "Permanently delete your account and sign out of this session." msgstr "アカウントを完全に削除し、このセッションからサインアウトします。" @@ -3048,7 +3148,17 @@ msgstr "記事のタイトルを入力してください。" msgid "Please enter your Fediverse handle." msgstr "フェディバースのハンドルを入力してください。" -#: src/routes/(root)/[handle]/settings/account.tsx:184 +#: src/routes/(root)/[handle]/settings/account.tsx:273 +#: src/routes/(root)/[handle]/settings/account.tsx:324 +msgid "Please sign in again before changing account migration settings." +msgstr "アカウント移行設定を変更する前にもう一度サインインしてください。" + +#: src/routes/(root)/[handle]/settings/account.tsx:273 +#: src/routes/(root)/[handle]/settings/account.tsx:322 +#~ msgid "Please sign in again before changing migration aliases." +#~ msgstr "移行エイリアスを変更する前にもう一度ログインしてください。" + +#: src/routes/(root)/[handle]/settings/account.tsx:502 msgid "Please sign in again before deleting your account." msgstr "アカウントを削除する前に、もう一度サインインしてください。" @@ -3168,12 +3278,28 @@ msgstr "優先共有者を削除しました。" msgid "Preferred sharers" msgstr "優先共有者" +#: src/routes/(root)/[handle]/settings/account.tsx:187 +msgid "Prepare this account as the destination for a Mastodon-style move." +msgstr "このアカウントをMastodon式の移行先として準備します。" + #: src/components/article-composer/ArticleComposerForm.tsx:111 #: src/components/MarkdownEditor.tsx:164 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/edit.tsx:427 msgid "Preview" msgstr "プレビュー" +#: src/routes/(root)/[handle]/settings/account.tsx:362 +#~ msgid "Previous account" +#~ msgstr "以前のアカウント" + +#: src/routes/(root)/[handle]/settings/account.tsx:264 +msgid "Previous account added" +msgstr "古いアカウントを追加しました" + +#: src/routes/(root)/[handle]/settings/account.tsx:315 +msgid "Previous account removed" +msgstr "古いアカウントを削除しました" + #: src/components/ImageLightbox.tsx:80 msgid "Previous image" msgstr "前の画像" @@ -3186,7 +3312,7 @@ msgstr "過去の違反履歴" msgid "Priority" msgstr "優先度" -#: src/components/AppSidebar.tsx:879 +#: src/components/AppSidebar.tsx:862 #: src/routes/(root)/privacy.tsx:40 msgid "Privacy policy" msgstr "プライバシーポリシー" @@ -3340,7 +3466,7 @@ msgstr "このタブを閉じていても新しい通知をすぐに受け取れ msgid "Receive notifications immediately through this browser, even when this tab is closed." msgstr "このブラウザーで通知をすぐに受け取ります。このタブを閉じていても通知されます。" -#: src/components/AppSidebar.tsx:790 +#: src/components/AppSidebar.tsx:773 msgid "Recent drafts" msgstr "最近の下書き" @@ -3447,6 +3573,7 @@ msgid "Remote follow" msgstr "リモートフォロー" #: src/components/LanguageList.tsx:225 +#: src/routes/(root)/[handle]/settings/account.tsx:437 #: src/routes/(root)/admin/news.tsx:669 #: src/routes/(root)/admin/news.tsx:805 msgid "Remove" @@ -3457,6 +3584,10 @@ msgstr "削除" msgid "Remove {0}" msgstr "{0}を削除" +#: src/routes/(root)/[handle]/settings/account.tsx:433 +msgid "Remove {alias}" +msgstr "{alias}を削除" + #: src/components/BookmarkButton.tsx:150 #: src/components/BookmarkButton.tsx:151 msgid "Remove bookmark" @@ -3504,6 +3635,10 @@ msgstr "引用を削除" msgid "Removes stored media that are old enough and no longer attached to an avatar, note, article draft, or article." msgstr "作成から十分な時間が経過し、アイコン、投稿、記事の下書き、記事のいずれにも添付されていない保存済みメディアを削除します。" +#: src/routes/(root)/[handle]/settings/account.tsx:437 +msgid "Removing…" +msgstr "削除中…" + #: src/components/article-composer/ArticleComposerForm.tsx:134 #: src/components/MarkdownEditor.tsx:181 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/edit.tsx:453 @@ -3668,7 +3803,7 @@ msgid "Saving…" msgstr "保存中…" #: src/components/admin/AdminAccountsTable.tsx:202 -#: src/components/AppSidebar.tsx:363 +#: src/components/AppSidebar.tsx:346 #: src/components/SearchForm.tsx:65 #: src/components/SearchForm.tsx:80 #: src/routes/(root)/admin/moderation/index.tsx:192 @@ -3742,7 +3877,7 @@ msgstr "タグはスペースで区切ります。タグを付けると読者が msgid "Set your personal preferences." msgstr "個人の環境設定を設定してください。" -#: src/components/AppSidebar.tsx:639 +#: src/components/AppSidebar.tsx:622 msgid "Settings" msgstr "設定" @@ -3823,12 +3958,14 @@ msgstr "モデレーションチーム名義で通報されたユーザーに表 msgid "Shown to the user" msgstr "ユーザーに表示" -#: src/components/AppSidebar.tsx:540 +#: src/components/AppSidebar.tsx:523 #: src/routes/(root)/sign/index.tsx:419 msgid "Sign in" msgstr "ログイン" -#: src/routes/(root)/[handle]/settings/account.tsx:183 +#: src/routes/(root)/[handle]/settings/account.tsx:272 +#: src/routes/(root)/[handle]/settings/account.tsx:323 +#: src/routes/(root)/[handle]/settings/account.tsx:501 msgid "Sign in required" msgstr "サインインが必要です" @@ -3848,7 +3985,7 @@ msgstr "ログインして投票" msgid "Sign in with passkey" msgstr "パスキーでサインイン" -#: src/components/AppSidebar.tsx:851 +#: src/components/AppSidebar.tsx:834 msgid "Sign out" msgstr "ログアウト" @@ -4090,8 +4227,9 @@ msgstr "共有のデフォルト公開設定です。" msgid "The default quote permission for your notes." msgstr "投稿のデフォルト引用許可設定です。" -#: src/routes/(root)/[handle]/settings/account.tsx:200 -#: src/routes/(root)/[handle]/settings/account.tsx:211 +#: src/routes/(root)/[handle]/settings/account.tsx:479 +#: src/routes/(root)/[handle]/settings/account.tsx:518 +#: src/routes/(root)/[handle]/settings/account.tsx:529 msgid "The deletion request could not be completed. Please try again." msgstr "削除リクエストを完了できませんでした。もう一度お試しください。" @@ -4136,6 +4274,15 @@ msgstr "招待リンクが正常に削除されました。" msgid "The link to this story is added to your post automatically." msgstr "この話題のリンクは自動的にコンテンツに追加されます。" +#: src/routes/(root)/[handle]/settings/account.tsx:293 +#~ msgid "The migration alias could not be added. Please try again." +#~ msgstr "移行エイリアスを追加できませんでした。もう一度お試しください。" + +#: src/routes/(root)/[handle]/settings/account.tsx:335 +#: src/routes/(root)/[handle]/settings/account.tsx:343 +#~ msgid "The migration alias could not be removed. Please try again." +#~ msgstr "移行エイリアスを削除できませんでした。もう一度お試しください。" + #: src/components/AppealDialog.tsx:103 msgid "The moderation team will review your appeal and notify you." msgstr "モデレーションチームが異議を審査し、あなたに通知します。" @@ -4148,6 +4295,15 @@ msgstr "お探しのページは存在しないか、移動された可能性が msgid "The passkey has been successfully revoked." msgstr "パスキーを正常に取り消しました。" +#: src/routes/(root)/[handle]/settings/account.tsx:294 +msgid "The previous account could not be added. Please try again." +msgstr "古いアカウントを追加できませんでした。もう一度お試しください。" + +#: src/routes/(root)/[handle]/settings/account.tsx:337 +#: src/routes/(root)/[handle]/settings/account.tsx:345 +msgid "The previous account could not be removed. Please try again." +msgstr "古いアカウントを削除できませんでした。もう一度お試しください。" + #: src/components/article-composer/ArticleComposerPublishFields.tsx:60 msgid "The primary language of your article, used for accessibility and discovery." msgstr "記事の主言語です。アクセシビリティや検索に使用されます。" @@ -4167,7 +4323,7 @@ msgstr "登録リンクが無効です。受信したメールのリンクを正 #. placeholder {0}: "GITHUB_REPOSITORY" #. placeholder {1}: "AGPL-3.0" -#: src/components/AppSidebar.tsx:903 +#: src/components/AppSidebar.tsx:886 msgid "The source code of this website is available on {0} under the {1} license." msgstr "このウェブサイトのソースコードは{1}ライセンスで{0}で公開されています。" @@ -4192,7 +4348,7 @@ msgstr "Web Push の公開鍵が無効です。" msgid "There are no moderation actions on your account." msgstr "あなたのアカウントに対するモデレーション対応はありません。" -#: src/routes/(root)/[handle]/settings/account.tsx:176 +#: src/routes/(root)/[handle]/settings/account.tsx:494 msgid "This account cannot be deleted right now. Please contact the instance administrators." msgstr "現在、このアカウントは削除できません。インスタンス管理者にお問い合わせください。" @@ -4212,7 +4368,7 @@ msgstr "このアカウントは停止されています。" msgid "This action cannot be undone. This will permanently delete this post." msgstr "この操作は取り消せません。このコンテンツは完全に削除されます。" -#: src/routes/(root)/[handle]/settings/account.tsx:223 +#: src/routes/(root)/[handle]/settings/account.tsx:541 msgid "This action is permanent." msgstr "この操作は永続的です。" @@ -4221,7 +4377,7 @@ msgstr "この操作は永続的です。" msgid "This browser does not support Web Push." msgstr "このブラウザーは Web Push に対応していません。" -#: src/routes/(root)/[handle]/settings/account.tsx:264 +#: src/routes/(root)/[handle]/settings/account.tsx:583 msgid "This cannot be undone. Your account will be deleted and you will be signed out." msgstr "この操作は元に戻せません。アカウントが削除され、サインアウトされます。" @@ -4264,6 +4420,10 @@ msgstr "ローカルの通知や異議申し立てがないリモートアクタ msgid "This is too long (maximum {MAX_REASON_LENGTH} characters)." msgstr "長すぎます(最大{MAX_REASON_LENGTH}文字)。" +#: src/routes/(root)/[handle]/settings/account.tsx:356 +msgid "This page only prepares the Hackers' Pub side of the move. The move still starts from your old server." +msgstr "このページでは、Hackers' Pub側の移行準備だけを行います。移行の開始は古いサーバーから行います。" + #: src/components/QuoteTargetPlaceholder.tsx:36 msgid "This post quoted another post, but the quote is not currently authorized." msgstr "このコンテンツは別のコンテンツを引用していましたが、現在この引用は許可されていません。" @@ -4308,7 +4468,7 @@ msgstr "通常1分ほどかかります。翻訳が完了するとページが msgid "This will be part of the article URL." msgstr "これは記事のURLの一部になります。" -#: src/components/AppSidebar.tsx:167 +#: src/components/AppSidebar.tsx:150 msgid "Timeline" msgstr "タイムライン" @@ -4357,9 +4517,9 @@ msgstr "{name}に翻訳中…" msgid "Translating…" msgstr "翻訳中…" -#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:379 -#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:402 -#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:411 +#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:391 +#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:414 +#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:423 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/index.tsx:615 msgid "Translation request failed" msgstr "翻訳のリクエストに失敗しました" @@ -4383,7 +4543,7 @@ msgid "Try again" msgstr "再試行" #. placeholder {0}: props.username -#: src/routes/(root)/[handle]/settings/account.tsx:241 +#: src/routes/(root)/[handle]/settings/account.tsx:560 msgid "Type {0} to confirm account deletion." msgstr "アカウント削除を確認するには{0}と入力してください。" @@ -4472,10 +4632,14 @@ msgstr "URL" msgid "URL pattern" msgstr "URLパターン" -#: src/components/AppSidebar.tsx:504 +#: src/components/AppSidebar.tsx:487 msgid "Use old UI" msgstr "旧UIを使う" +#: src/routes/(root)/[handle]/settings/account.tsx:375 +#~ msgid "Use the old account's handle or actor URL." +#~ msgstr "古いアカウントのハンドルまたはアクターURLを使用してください。" + #: src/components/ProfileActionMenu.tsx:320 msgid "User blocked" msgstr "ユーザーをブロックしました" @@ -4498,7 +4662,7 @@ msgstr "ユーザーのブロックを解除しました" msgid "User unmuted" msgstr "ユーザーのミュートを解除しました" -#: src/routes/(root)/[handle]/settings/account.tsx:234 +#: src/routes/(root)/[handle]/settings/account.tsx:552 #: src/routes/(root)/[handle]/settings/index.tsx:423 #: src/routes/(root)/sign/up/[token].tsx:331 msgid "Username" @@ -4538,7 +4702,7 @@ msgstr "{1}に{0}さんがこのリンクの所有者であることを確認済 msgid "Verifying your invitation…" msgstr "招待を確認中…" -#: src/components/AppSidebar.tsx:814 +#: src/components/AppSidebar.tsx:797 msgid "View all drafts →" msgstr "すべての下書きを表示 →" @@ -4677,7 +4841,7 @@ msgstr "決定を撤回" msgid "Withdrawn" msgstr "撤回" -#: src/components/AppSidebar.tsx:263 +#: src/components/AppSidebar.tsx:246 msgid "Without shares" msgstr "共有除外" @@ -4740,7 +4904,12 @@ msgstr "画像は最大{MAX_MEDIA}枚まで添付できます" msgid "You can change it only once, and the old username will become available to others." msgstr "変更は1回のみ可能で、変更前のユーザー名は他のユーザーが使用できるようになります。" -#: src/routes/(root)/[handle]/settings/account.tsx:192 +#: src/routes/(root)/[handle]/settings/account.tsx:280 +#: src/routes/(root)/[handle]/settings/account.tsx:329 +#~ msgid "You can change migration aliases only for your own account." +#~ msgstr "自分のアカウントの移行エイリアスのみ変更できます。" + +#: src/routes/(root)/[handle]/settings/account.tsx:510 msgid "You can delete only your own account." msgstr "自分のアカウントのみ削除できます。" @@ -4769,6 +4938,11 @@ msgstr "自分のブックマークのみ表示できます" msgid "You can only view your own drafts" msgstr "自分の下書きのみ表示できます" +#: src/routes/(root)/[handle]/settings/account.tsx:280 +#: src/routes/(root)/[handle]/settings/account.tsx:331 +msgid "You can prepare migration only for your own account." +msgstr "自分のアカウントでのみ移行を準備できます。" + #: src/routes/(root)/[handle]/settings/passkeys.tsx:405 msgid "You don't have any passkeys registered yet." msgstr "まだパスキーが登録されていません。" @@ -4856,6 +5030,14 @@ msgstr "Hackers' Pubに招待されました" msgid "Your account is suspended, so you can't post right now. See your sanctions for details and how to appeal." msgstr "あなたのアカウントは停止されているため、現在投稿できません。詳細と異議申し立ての方法は制裁履歴をご確認ください。" +#: src/routes/(root)/[handle]/settings/account.tsx:266 +#~ msgid "Your actor document now includes the previous account." +#~ msgstr "アクター文書に以前のアカウントが含まれました。" + +#: src/routes/(root)/[handle]/settings/account.tsx:315 +#~ msgid "Your actor document was updated." +#~ msgstr "アクター文書を更新しました。" + #: src/components/ModerationNotificationList.tsx:119 msgid "Your appeal was reviewed." msgstr "あなたの異議申し立てが審査されました。" @@ -4909,7 +5091,7 @@ msgstr "優先言語が更新されました。" msgid "Your profile settings have been updated successfully." msgstr "プロフィール設定が正常に更新されました。" -#: src/routes/(root)/[handle]/settings/account.tsx:226 +#: src/routes/(root)/[handle]/settings/account.tsx:544 msgid "Your profile, posts, drafts, follows, settings, and login credentials will be removed. Your current username will remain reserved." msgstr "プロフィール、コンテンツ、下書き、フォロー、設定、ログイン認証情報が削除されます。現在のユーザー名は引き続き予約されます。" diff --git a/web-next/src/locales/ko-KR/messages.po b/web-next/src/locales/ko-KR/messages.po index c65184c5d..14d0c206f 100644 --- a/web-next/src/locales/ko-KR/messages.po +++ b/web-next/src/locales/ko-KR/messages.po @@ -113,7 +113,7 @@ msgid "{0, plural, one {Load # more reactor} other {Load # more reactors}}" msgstr "{0, plural, one {반응자 #명 더 불러오기} other {반응자 #명 더 불러오기}}" #. placeholder {0}: props.count -#: src/components/AppSidebar.tsx:457 +#: src/components/AppSidebar.tsx:440 msgid "{0, plural, one {Notifications (# unread)} other {Notifications (# unread)}}" msgstr "{0, plural, other {알림 (읽지 않음 #개)}}" @@ -320,8 +320,8 @@ msgid "{0}'s following" msgstr "{0} 님의 팔로잉" #. placeholder {0}: actor.rawName ?? actor.username -#: src/routes/(root)/[handle]/(profile)/interactions.tsx:103 -#: src/routes/(root)/[handle]/(profile)/interactions.tsx:107 +#: src/routes/(root)/[handle]/(profile)/interactions.tsx:100 +#: src/routes/(root)/[handle]/(profile)/interactions.tsx:104 msgid "{0}'s interactions" msgstr "{0} 님과의 상호작용" @@ -366,6 +366,10 @@ msgstr "{days}일" msgid "{HIGH_PRIORITY_REPORT_COUNT}+ reports" msgstr "신고 {HIGH_PRIORITY_REPORT_COUNT}건 이상" +#: src/routes/(root)/[handle]/settings/account.tsx:387 +msgid "@old@example.com or actor URL" +msgstr "@old@example.com 또는 액터 URL" + #: src/routes/(root)/[handle]/[idOrYear]/[slug]/reactions.tsx:231 #: src/routes/(root)/[handle]/[noteId]/reactions.tsx:253 #~ msgid "+{0} more reactor(s) not shown" @@ -452,12 +456,12 @@ msgid "A user (profile) report." msgstr "사용자(프로필) 신고입니다." #: src/components/admin/AdminAccountsTable.tsx:224 -#: src/components/AppSidebar.tsx:498 +#: src/components/AppSidebar.tsx:481 #: src/components/SettingsTabs.tsx:112 msgid "Account" msgstr "계정" -#: src/routes/(root)/[handle]/settings/account.tsx:174 +#: src/routes/(root)/[handle]/settings/account.tsx:492 msgid "Account deletion is unavailable" msgstr "계정 삭제를 사용할 수 없습니다" @@ -465,11 +469,15 @@ msgstr "계정 삭제를 사용할 수 없습니다" msgid "Account handle" msgstr "계정 핸들" +#: src/routes/(root)/[handle]/settings/account.tsx:185 +msgid "Account migration" +msgstr "계정 이전" + #: src/routes/(root)/[handle]/settings/sanctions.tsx:94 msgid "Account permanently suspended" msgstr "계정 영구 정지됨" -#: src/routes/(root)/[handle]/settings/account.tsx:124 +#: src/routes/(root)/[handle]/settings/account.tsx:179 msgid "Account settings" msgstr "계정 설정" @@ -503,6 +511,7 @@ msgstr "활성화 시점:" msgid "Actors currently under an active suspension or federation block. Expired suspensions drop off automatically." msgstr "현재 정지 또는 연합 차단 중인 액터입니다. 만료된 정지는 자동으로 제외됩니다." +#: src/routes/(root)/[handle]/settings/account.tsx:407 #: src/routes/(root)/[handle]/settings/language.tsx:196 #: src/routes/(root)/admin/news.tsx:639 #: src/routes/(root)/admin/news.tsx:748 @@ -527,10 +536,15 @@ msgstr "선택지 추가" msgid "Add poll" msgstr "설문 추가" +#: src/routes/(root)/[handle]/settings/account.tsx:360 +msgid "Add the old account here. Hackers' Pub will publish it as another account that belongs to you." +msgstr "예전 계정을 여기에 추가하세요. Hackers' Pub은 이 계정을 회원님의 다른 계정으로 공개합니다." + #: src/components/HashtagActionBar.tsx:258 msgid "Add to sidebar" msgstr "사이드바에 추가" +#: src/routes/(root)/[handle]/settings/account.tsx:407 #: src/routes/(root)/admin/news.tsx:639 #: src/routes/(root)/admin/news.tsx:748 msgid "Adding…" @@ -540,10 +554,18 @@ msgstr "추가 중…" msgid "Additional context (optional)" msgstr "추가 설명 (선택)" -#: src/components/AppSidebar.tsx:649 +#: src/components/AppSidebar.tsx:632 msgid "Admin" msgstr "관리" +#: src/routes/(root)/[handle]/settings/account.tsx:187 +#~ msgid "Advertise previous accounts before starting the move from the old server." +#~ msgstr "이전 서버에서 이전을 시작하기 전에 예전 계정을 표시합니다." + +#: src/routes/(root)/[handle]/settings/account.tsx:366 +msgid "After the old server confirms the destination, it sends the Move activity and compatible servers can move followers here." +msgstr "예전 서버가 이전 대상을 확인하면 Move 액티비티를 보내며, 호환되는 서버는 팔로워를 이곳으로 이전할 수 있습니다." + #: src/routes/(root)/[handle]/bookmarks.tsx:136 #: src/routes/(root)/admin/moderation/appeals.tsx:157 #: src/routes/(root)/admin/moderation/index.tsx:123 @@ -749,7 +771,7 @@ msgstr "게시글-url-슬러그" msgid "Articles" msgstr "게시글" -#: src/components/AppSidebar.tsx:289 +#: src/components/AppSidebar.tsx:272 #: src/components/ProfileCard.tsx:197 msgid "Articles only" msgstr "게시글만" @@ -841,7 +863,7 @@ msgstr "굵게" msgid "Bookmark" msgstr "북마크" -#: src/components/AppSidebar.tsx:585 +#: src/components/AppSidebar.tsx:568 #: src/routes/(root)/[handle]/bookmarks.tsx:126 msgid "Bookmarks" msgstr "북마크" @@ -907,7 +929,7 @@ msgstr "{0} 작성" #: src/components/RemoveFollowerButton.tsx:144 #: src/components/ReportDialog.tsx:224 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/edit.tsx:523 -#: src/routes/(root)/[handle]/settings/account.tsx:269 +#: src/routes/(root)/[handle]/settings/account.tsx:588 #: src/routes/(root)/[handle]/settings/index.tsx:408 #: src/routes/(root)/[handle]/settings/passkeys.tsx:522 #: src/routes/(root)/authorize_interaction.tsx:273 @@ -918,10 +940,15 @@ msgstr "취소" msgid "Cannot change the language because translations already exist" msgstr "번역이 이미 존재하므로 언어를 변경할 수 없습니다" -#: src/routes/(root)/[handle]/settings/account.tsx:191 +#: src/routes/(root)/[handle]/settings/account.tsx:509 msgid "Cannot delete this account" msgstr "이 계정을 삭제할 수 없습니다" +#: src/routes/(root)/[handle]/settings/account.tsx:279 +#: src/routes/(root)/[handle]/settings/account.tsx:330 +msgid "Cannot update this account" +msgstr "이 계정을 업데이트할 수 없습니다" + #: src/components/admin/ModerationSubTabs.tsx:28 msgid "Cases" msgstr "케이스" @@ -1001,7 +1028,7 @@ msgstr "닫힘" msgid "Code" msgstr "코드" -#: src/components/AppSidebar.tsx:872 +#: src/components/AppSidebar.tsx:855 #: src/routes/(root)/coc.tsx:40 #: src/routes/(root)/sign/up/[token].tsx:458 msgid "Code of conduct" @@ -1016,7 +1043,7 @@ msgstr "행동 강령: {0}" #~ msgid "Comments ({0})" #~ msgstr "댓글 ({0})" -#: src/components/AppSidebar.tsx:709 +#: src/components/AppSidebar.tsx:692 #: src/components/FloatingComposeButton.tsx:61 msgid "Compose" msgstr "작성" @@ -1051,6 +1078,16 @@ msgstr "복사됨" msgid "Copy" msgstr "복사" +#: src/routes/(root)/[handle]/settings/account.tsx:286 +#: src/routes/(root)/[handle]/settings/account.tsx:292 +#~ msgid "Could not add migration alias" +#~ msgstr "이전 별칭을 추가할 수 없습니다" + +#: src/routes/(root)/[handle]/settings/account.tsx:287 +#: src/routes/(root)/[handle]/settings/account.tsx:293 +msgid "Could not add previous account" +msgstr "예전 계정을 추가할 수 없습니다" + #: src/routes/(root)/[handle]/settings/invite.tsx:638 msgid "Could not copy the link to the clipboard." msgstr "클립보드에 링크를 복사할 수 없습니다." @@ -1073,6 +1110,16 @@ msgstr "조치를 기록하지 못했습니다" msgid "Could not refresh this from its origin." msgstr "이 항목을 원본에서 새로 고치지 못했습니다." +#: src/routes/(root)/[handle]/settings/account.tsx:334 +#: src/routes/(root)/[handle]/settings/account.tsx:342 +#~ msgid "Could not remove migration alias" +#~ msgstr "이전 별칭을 제거할 수 없습니다" + +#: src/routes/(root)/[handle]/settings/account.tsx:336 +#: src/routes/(root)/[handle]/settings/account.tsx:344 +msgid "Could not remove previous account" +msgstr "예전 계정을 제거할 수 없습니다" + #: src/routes/(root)/admin/refresh.tsx:129 msgid "Could not resolve that as a remote object." msgstr "원격 객체로 확인할 수 없습니다." @@ -1096,7 +1143,7 @@ msgstr "이의 제기를 제출하지 못했습니다" msgid "Could not vote on this poll" msgstr "이 설문에 투표할 수 없습니다" -#: src/components/AppSidebar.tsx:754 +#: src/components/AppSidebar.tsx:737 #: src/components/FloatingComposeButton.tsx:123 msgid "Create article" msgstr "게시글 작성" @@ -1105,7 +1152,7 @@ msgstr "게시글 작성" msgid "Create invitation link" msgstr "초대 링크 생성" -#: src/components/AppSidebar.tsx:731 +#: src/components/AppSidebar.tsx:714 #: src/components/FloatingComposeButton.tsx:99 #: src/components/NoteComposeModal.tsx:78 #: src/components/NoteComposer.tsx:1873 @@ -1191,13 +1238,13 @@ msgstr "기본 공유 공개 범위" msgid "Delete" msgstr "삭제" -#: src/routes/(root)/[handle]/settings/account.tsx:125 -#: src/routes/(root)/[handle]/settings/account.tsx:253 -#: src/routes/(root)/[handle]/settings/account.tsx:278 +#: src/routes/(root)/[handle]/settings/account.tsx:199 +#: src/routes/(root)/[handle]/settings/account.tsx:572 +#: src/routes/(root)/[handle]/settings/account.tsx:597 msgid "Delete account" msgstr "계정 삭제" -#: src/routes/(root)/[handle]/settings/account.tsx:261 +#: src/routes/(root)/[handle]/settings/account.tsx:580 msgid "Delete account permanently?" msgstr "계정을 영구적으로 삭제할까요?" @@ -1215,7 +1262,7 @@ msgid "Delete post?" msgstr "콘텐츠를 삭제할까요?" #: src/components/article-composer/ArticleComposerActions.tsx:21 -#: src/routes/(root)/[handle]/settings/account.tsx:278 +#: src/routes/(root)/[handle]/settings/account.tsx:597 #: src/routes/(root)/[handle]/settings/invite.tsx:745 #: src/routes/(root)/admin/media.tsx:189 msgid "Deleting…" @@ -1360,6 +1407,18 @@ msgstr "종료됨" msgid "Ends" msgstr "종료까지" +#: src/routes/(root)/[handle]/settings/account.tsx:284 +#~ msgid "Enter a valid previous account handle or actor URL." +#~ msgstr "유효한 예전 계정 핸들 또는 액터 URL을 입력해 주세요." + +#: src/routes/(root)/[handle]/settings/account.tsx:394 +msgid "Enter the account you are moving from, for example @old@example.com." +msgstr "이전해 오려는 계정을 입력하세요. 예: @old@example.com." + +#: src/routes/(root)/[handle]/settings/account.tsx:285 +msgid "Enter the account you are moving from, such as @old@example.com or its actor URL." +msgstr "이전해 오려는 계정을 입력하세요. @old@example.com 또는 액터 URL을 사용할 수 있습니다." + #: src/routes/(root)/[handle]/invite/[id].tsx:284 msgid "Enter your email address below to get started." msgstr "아래에 이메일 주소를 입력하여 시작하세요." @@ -1492,8 +1551,9 @@ msgstr "복사 실패" msgid "Failed to create invitation link" msgstr "초대 링크 생성에 실패했습니다" -#: src/routes/(root)/[handle]/settings/account.tsx:198 -#: src/routes/(root)/[handle]/settings/account.tsx:209 +#: src/routes/(root)/[handle]/settings/account.tsx:477 +#: src/routes/(root)/[handle]/settings/account.tsx:516 +#: src/routes/(root)/[handle]/settings/account.tsx:527 msgid "Failed to delete account" msgstr "계정 삭제 실패" @@ -1736,7 +1796,7 @@ msgid "Failed to share post" msgstr "콘텐츠 공유 실패" #. placeholder {0}: error.message -#: src/components/AppSidebar.tsx:144 +#: src/components/AppSidebar.tsx:127 msgid "Failed to sign out: {0}" msgstr "로그아웃 실패: {0}" @@ -1814,7 +1874,7 @@ msgstr "투표에 실패했습니다" msgid "Favor links shared by specific accounts. A preferred sharer's posts count toward the news feed even when the account is a bot (for example a feed that reposts Hacker News links), and the links it shares get a flat promotion bonus in the popular ranking. A penalty on a link overrides the promotion." msgstr "특정 계정이 공유한 링크를 우대합니다. 우대 공유자의 콘텐츠는 해당 계정이 봇이어도 (예: Hacker News 링크를 다시 공유하는 피드) 뉴스 피드에 집계되며, 그 계정이 공유한 링크는 인기 순위에서 고정 가산점을 받습니다. 링크에 패널티가 걸리면 우대보다 패널티가 우선합니다." -#: src/components/AppSidebar.tsx:341 +#: src/components/AppSidebar.tsx:324 msgid "Fediverse" msgstr "연합우주" @@ -1822,7 +1882,7 @@ msgstr "연합우주" msgid "Fediverse handle" msgstr "연합우주 핸들" -#: src/components/AppSidebar.tsx:220 +#: src/components/AppSidebar.tsx:203 msgid "Feed" msgstr "피드" @@ -1889,7 +1949,7 @@ msgstr "생성 중…" msgid "Get browser notifications" msgstr "브라우저 알림 받기" -#: src/components/AppSidebar.tsx:912 +#: src/components/AppSidebar.tsx:895 msgid "GitHub repository" msgstr "GitHub 저장소" @@ -1927,8 +1987,8 @@ msgstr "마지막 재발급 시점 이후 가장 활발한 계정(콘텐츠 수 msgid "Graph" msgstr "그래프" -#: src/components/AppSidebar.tsx:307 -#: src/components/AppSidebar.tsx:429 +#: src/components/AppSidebar.tsx:290 +#: src/components/AppSidebar.tsx:412 #: src/routes/(root).tsx:196 #: src/routes/(root)/coc.tsx:40 #: src/routes/(root)/markdown.tsx:40 @@ -1945,6 +2005,22 @@ msgstr "Hackers' Pub 홈" msgid "Hackers' Pub is a place for software engineers to share their knowledge and experience with each other. It's also an ActivityPub-enabled social network, so you can follow your favorite hackers in the fediverse and get their latest posts in your feed." msgstr "Hackers' Pub은 소프트웨어 프로그래머들이 지식과 경험을 서로 나누는 곳입니다. 또한 ActivityPub을 지원하는 소셜 네트워크이기도 하며, 연합우주(fediverse)에서 즐겨찾는 소프트웨어 프로그래머들을 팔로하고 최신 콘텐츠를 받아 볼 수 있습니다." +#: src/routes/(root)/[handle]/settings/account.tsx:317 +#~ msgid "Hackers' Pub no longer publishes that account as an alias." +#~ msgstr "Hackers' Pub은 더 이상 그 계정을 별칭으로 공개하지 않습니다." + +#: src/routes/(root)/[handle]/settings/account.tsx:317 +msgid "Hackers' Pub no longer publishes that account as another account that belongs to you." +msgstr "Hackers' Pub은 더 이상 그 계정을 회원님의 다른 계정으로 공개하지 않습니다." + +#: src/routes/(root)/[handle]/settings/account.tsx:266 +msgid "Hackers' Pub now publishes the old account as another account that belongs to you." +msgstr "Hackers' Pub은 이제 예전 계정을 회원님의 다른 계정으로 공개합니다." + +#: src/routes/(root)/[handle]/settings/account.tsx:266 +#~ msgid "Hackers' Pub now publishes the old account as belonging to you." +#~ msgstr "Hackers' Pub은 이제 예전 계정이 회원님의 계정임을 공개합니다." + #: src/routes/(root)/admin/index.tsx:88 msgid "Hackers' Pub: Admin · Accounts" msgstr "Hackers' Pub: 관리 · 계정" @@ -2143,7 +2219,7 @@ msgstr "초대 링크" msgid "Invitation sent" msgstr "초대장이 발송되었습니다" -#: src/components/AppSidebar.tsx:864 +#: src/components/AppSidebar.tsx:847 #: src/routes/(root)/[handle]/settings/invite.tsx:910 #: src/routes/(root)/tree/graph.tsx:79 #: src/routes/(root)/tree/index.tsx:206 @@ -2159,7 +2235,7 @@ msgstr "초대" msgid "Invitations left" msgstr "남은 초대장" -#: src/components/AppSidebar.tsx:608 +#: src/components/AppSidebar.tsx:591 #: src/components/SettingsTabs.tsx:72 #: src/routes/(root)/[handle]/settings/invite.tsx:311 msgid "Invite" @@ -2517,6 +2593,14 @@ msgstr "언급된 사용자만" msgid "Message to the user (optional)" msgstr "사용자에게 보낼 메시지 (선택)" +#: src/routes/(root)/[handle]/settings/account.tsx:264 +#~ msgid "Migration alias added" +#~ msgstr "이전 별칭이 추가되었습니다" + +#: src/routes/(root)/[handle]/settings/account.tsx:314 +#~ msgid "Migration alias removed" +#~ msgstr "이전 별칭이 제거되었습니다" + #: src/components/ReportDialog.tsx:192 msgid "Minimum {MIN_REASON_LENGTH} characters required." msgstr "최소 {MIN_REASON_LENGTH}자 이상 입력해야 합니다." @@ -2645,7 +2729,7 @@ msgid "Newest" msgstr "최신" #: src/components/AdminTabs.tsx:58 -#: src/components/AppSidebar.tsx:193 +#: src/components/AppSidebar.tsx:176 #: src/routes/(root)/admin/news.tsx:555 #: src/routes/(root)/news/index.tsx:48 msgid "News" @@ -2726,6 +2810,10 @@ msgstr "남은 초대장이 없습니다" msgid "No matching object found" msgstr "일치하는 객체를 찾을 수 없습니다" +#: src/routes/(root)/[handle]/settings/account.tsx:397 +#~ msgid "No migration aliases yet." +#~ msgstr "아직 이전 별칭이 없습니다." + #: src/components/ActorArticleList.tsx:93 msgid "No notes articles" msgstr "게시글이 없습니다" @@ -2768,6 +2856,10 @@ msgstr "아직 우대 공유자가 없습니다." msgid "No previews" msgstr "미리보기 없음" +#: src/routes/(root)/[handle]/settings/account.tsx:416 +msgid "No previous accounts added yet." +msgstr "아직 예전 계정이 추가되지 않았습니다." + #: src/routes/(root)/admin/moderation/statistics.tsx:223 msgid "No provisions have been cited yet." msgstr "아직 인용된 조항이 없습니다." @@ -2884,8 +2976,8 @@ msgstr "알림 권한이 허용되지 않았습니다." msgid "Notification preview privacy" msgstr "알림 미리보기 개인정보" -#: src/components/AppSidebar.tsx:464 -#: src/components/AppSidebar.tsx:465 +#: src/components/AppSidebar.tsx:447 +#: src/components/AppSidebar.tsx:448 #: src/routes/(root).tsx:214 #: src/routes/(root).tsx:215 msgid "Notifications" @@ -2904,6 +2996,14 @@ msgstr "브라우저 설정에서 알림이 차단되어 있습니다." msgid "Number of invitations" msgstr "초대 횟수" +#: src/routes/(root)/[handle]/settings/account.tsx:381 +msgid "Old account" +msgstr "예전 계정" + +#: src/routes/(root)/[handle]/settings/account.tsx:363 +msgid "On the old server, open account migration settings and set this Hackers' Pub account as the new account." +msgstr "예전 서버에서 계정 이전 설정을 열고 이 Hackers' Pub 계정을 새 계정으로 지정하세요." + #: src/components/RefreshFromOriginItem.tsx:79 #: src/routes/(root)/admin/refresh.tsx:136 msgid "Only moderators can refresh remote objects." @@ -3002,7 +3102,7 @@ msgstr "검토 대기 중" msgid "People you might want to follow" msgstr "팔로 추천" -#: src/routes/(root)/[handle]/settings/account.tsx:126 +#: src/routes/(root)/[handle]/settings/account.tsx:201 msgid "Permanently delete your account and sign out of this session." msgstr "계정을 영구적으로 삭제하고 이 세션에서 로그아웃합니다." @@ -3048,7 +3148,17 @@ msgstr "게시글 제목을 입력해주세요." msgid "Please enter your Fediverse handle." msgstr "연합우주 핸들을 입력해 주세요." -#: src/routes/(root)/[handle]/settings/account.tsx:184 +#: src/routes/(root)/[handle]/settings/account.tsx:273 +#: src/routes/(root)/[handle]/settings/account.tsx:324 +msgid "Please sign in again before changing account migration settings." +msgstr "계정 이전 설정을 변경하기 전에 다시 로그인해 주세요." + +#: src/routes/(root)/[handle]/settings/account.tsx:273 +#: src/routes/(root)/[handle]/settings/account.tsx:322 +#~ msgid "Please sign in again before changing migration aliases." +#~ msgstr "이전 별칭을 변경하기 전에 다시 로그인해 주세요." + +#: src/routes/(root)/[handle]/settings/account.tsx:502 msgid "Please sign in again before deleting your account." msgstr "계정을 삭제하기 전에 다시 로그인해 주세요." @@ -3168,12 +3278,28 @@ msgstr "우대 공유자를 제거했습니다." msgid "Preferred sharers" msgstr "우대 공유자" +#: src/routes/(root)/[handle]/settings/account.tsx:187 +msgid "Prepare this account as the destination for a Mastodon-style move." +msgstr "이 계정을 Mastodon 방식 이전의 대상 계정으로 준비합니다." + #: src/components/article-composer/ArticleComposerForm.tsx:111 #: src/components/MarkdownEditor.tsx:164 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/edit.tsx:427 msgid "Preview" msgstr "미리보기" +#: src/routes/(root)/[handle]/settings/account.tsx:362 +#~ msgid "Previous account" +#~ msgstr "예전 계정" + +#: src/routes/(root)/[handle]/settings/account.tsx:264 +msgid "Previous account added" +msgstr "예전 계정이 추가되었습니다" + +#: src/routes/(root)/[handle]/settings/account.tsx:315 +msgid "Previous account removed" +msgstr "예전 계정이 제거되었습니다" + #: src/components/ImageLightbox.tsx:80 msgid "Previous image" msgstr "이전 이미지" @@ -3186,7 +3312,7 @@ msgstr "이전 위반 이력" msgid "Priority" msgstr "우선순위" -#: src/components/AppSidebar.tsx:879 +#: src/components/AppSidebar.tsx:862 #: src/routes/(root)/privacy.tsx:40 msgid "Privacy policy" msgstr "개인정보 처리방침" @@ -3340,7 +3466,7 @@ msgstr "이 탭을 닫아도 새 알림을 즉시 받습니다." msgid "Receive notifications immediately through this browser, even when this tab is closed." msgstr "이 브라우저로 알림을 즉시 받습니다. 이 탭을 닫아도 알림을 받을 수 있습니다." -#: src/components/AppSidebar.tsx:790 +#: src/components/AppSidebar.tsx:773 msgid "Recent drafts" msgstr "최근 초고" @@ -3447,6 +3573,7 @@ msgid "Remote follow" msgstr "원격 팔로" #: src/components/LanguageList.tsx:225 +#: src/routes/(root)/[handle]/settings/account.tsx:437 #: src/routes/(root)/admin/news.tsx:669 #: src/routes/(root)/admin/news.tsx:805 msgid "Remove" @@ -3457,6 +3584,10 @@ msgstr "제거" msgid "Remove {0}" msgstr "{0} 제거" +#: src/routes/(root)/[handle]/settings/account.tsx:433 +msgid "Remove {alias}" +msgstr "{alias} 제거" + #: src/components/BookmarkButton.tsx:150 #: src/components/BookmarkButton.tsx:151 msgid "Remove bookmark" @@ -3504,6 +3635,10 @@ msgstr "인용 삭제" msgid "Removes stored media that are old enough and no longer attached to an avatar, note, article draft, or article." msgstr "생성된 지 충분히 오래되었고 프로필 사진, 단문, 게시글 초고, 게시글에 더 이상 첨부되어 있지 않은 저장된 미디어를 제거합니다." +#: src/routes/(root)/[handle]/settings/account.tsx:437 +msgid "Removing…" +msgstr "제거 중…" + #: src/components/article-composer/ArticleComposerForm.tsx:134 #: src/components/MarkdownEditor.tsx:181 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/edit.tsx:453 @@ -3668,7 +3803,7 @@ msgid "Saving…" msgstr "저장 중…" #: src/components/admin/AdminAccountsTable.tsx:202 -#: src/components/AppSidebar.tsx:363 +#: src/components/AppSidebar.tsx:346 #: src/components/SearchForm.tsx:65 #: src/components/SearchForm.tsx:80 #: src/routes/(root)/admin/moderation/index.tsx:192 @@ -3742,7 +3877,7 @@ msgstr "태그는 공백으로 구분합니다. 태그는 독자가 게시글을 msgid "Set your personal preferences." msgstr "개인의 환경 설정을 설정하세요." -#: src/components/AppSidebar.tsx:639 +#: src/components/AppSidebar.tsx:622 msgid "Settings" msgstr "설정" @@ -3823,12 +3958,14 @@ msgstr "모더레이션 팀 명의로 신고된 사용자에게 표시됩니다. msgid "Shown to the user" msgstr "사용자에게 표시됨" -#: src/components/AppSidebar.tsx:540 +#: src/components/AppSidebar.tsx:523 #: src/routes/(root)/sign/index.tsx:419 msgid "Sign in" msgstr "로그인" -#: src/routes/(root)/[handle]/settings/account.tsx:183 +#: src/routes/(root)/[handle]/settings/account.tsx:272 +#: src/routes/(root)/[handle]/settings/account.tsx:323 +#: src/routes/(root)/[handle]/settings/account.tsx:501 msgid "Sign in required" msgstr "로그인이 필요합니다" @@ -3848,7 +3985,7 @@ msgstr "로그인 후 투표" msgid "Sign in with passkey" msgstr "패스키를 사용하여 로그인" -#: src/components/AppSidebar.tsx:851 +#: src/components/AppSidebar.tsx:834 msgid "Sign out" msgstr "로그아웃" @@ -4090,8 +4227,9 @@ msgstr "공유의 기본 공개 설정입니다." msgid "The default quote permission for your notes." msgstr "단문의 기본 인용 권한 설정입니다." -#: src/routes/(root)/[handle]/settings/account.tsx:200 -#: src/routes/(root)/[handle]/settings/account.tsx:211 +#: src/routes/(root)/[handle]/settings/account.tsx:479 +#: src/routes/(root)/[handle]/settings/account.tsx:518 +#: src/routes/(root)/[handle]/settings/account.tsx:529 msgid "The deletion request could not be completed. Please try again." msgstr "삭제 요청을 완료할 수 없습니다. 다시 시도해 주세요." @@ -4136,6 +4274,15 @@ msgstr "초대 링크가 성공적으로 삭제되었습니다." msgid "The link to this story is added to your post automatically." msgstr "이 이야기의 링크가 콘텐츠에 자동으로 추가됩니다." +#: src/routes/(root)/[handle]/settings/account.tsx:293 +#~ msgid "The migration alias could not be added. Please try again." +#~ msgstr "이전 별칭을 추가하지 못했습니다. 다시 시도해 주세요." + +#: src/routes/(root)/[handle]/settings/account.tsx:335 +#: src/routes/(root)/[handle]/settings/account.tsx:343 +#~ msgid "The migration alias could not be removed. Please try again." +#~ msgstr "이전 별칭을 제거하지 못했습니다. 다시 시도해 주세요." + #: src/components/AppealDialog.tsx:103 msgid "The moderation team will review your appeal and notify you." msgstr "모더레이션 팀이 이의 제기를 검토하고 회원님에게 통지할 예정입니다." @@ -4148,6 +4295,15 @@ msgstr "찾으시는 페이지가 존재하지 않거나 이동되었습니다." msgid "The passkey has been successfully revoked." msgstr "성공적으로 패스키를 취소했습니다." +#: src/routes/(root)/[handle]/settings/account.tsx:294 +msgid "The previous account could not be added. Please try again." +msgstr "예전 계정을 추가하지 못했습니다. 다시 시도해 주세요." + +#: src/routes/(root)/[handle]/settings/account.tsx:337 +#: src/routes/(root)/[handle]/settings/account.tsx:345 +msgid "The previous account could not be removed. Please try again." +msgstr "예전 계정을 제거하지 못했습니다. 다시 시도해 주세요." + #: src/components/article-composer/ArticleComposerPublishFields.tsx:60 msgid "The primary language of your article, used for accessibility and discovery." msgstr "게시글의 주요 언어로, 접근성 및 검색에 활용됩니다." @@ -4167,7 +4323,7 @@ msgstr "가입 링크가 유효하지 않습니다. 이메일로 받은 링크 #. placeholder {0}: "GITHUB_REPOSITORY" #. placeholder {1}: "AGPL-3.0" -#: src/components/AppSidebar.tsx:903 +#: src/components/AppSidebar.tsx:886 msgid "The source code of this website is available on {0} under the {1} license." msgstr "이 웹사이트의 소스 코드는 {1} 라이선스로 {0}에서 배포됩니다." @@ -4192,7 +4348,7 @@ msgstr "Web Push 공개 키가 올바르지 않습니다." msgid "There are no moderation actions on your account." msgstr "회원님의 계정에 대한 모더레이션 조치가 없습니다." -#: src/routes/(root)/[handle]/settings/account.tsx:176 +#: src/routes/(root)/[handle]/settings/account.tsx:494 msgid "This account cannot be deleted right now. Please contact the instance administrators." msgstr "지금은 이 계정을 삭제할 수 없습니다. 인스턴스 관리자에게 문의해 주세요." @@ -4212,7 +4368,7 @@ msgstr "이 계정은 정지되었습니다." msgid "This action cannot be undone. This will permanently delete this post." msgstr "이 작업은 되돌릴 수 없습니다. 이 콘텐츠는 영구적으로 삭제됩니다." -#: src/routes/(root)/[handle]/settings/account.tsx:223 +#: src/routes/(root)/[handle]/settings/account.tsx:541 msgid "This action is permanent." msgstr "이 작업은 되돌릴 수 없습니다." @@ -4221,7 +4377,7 @@ msgstr "이 작업은 되돌릴 수 없습니다." msgid "This browser does not support Web Push." msgstr "이 브라우저는 Web Push를 지원하지 않습니다." -#: src/routes/(root)/[handle]/settings/account.tsx:264 +#: src/routes/(root)/[handle]/settings/account.tsx:583 msgid "This cannot be undone. Your account will be deleted and you will be signed out." msgstr "이 작업은 취소할 수 없습니다. 계정이 삭제되고 로그아웃됩니다." @@ -4264,6 +4420,10 @@ msgstr "로컬 통지나 이의 제기가 없는 원격 액터입니다. 경고 msgid "This is too long (maximum {MAX_REASON_LENGTH} characters)." msgstr "너무 깁니다 (최대 {MAX_REASON_LENGTH}자)." +#: src/routes/(root)/[handle]/settings/account.tsx:356 +msgid "This page only prepares the Hackers' Pub side of the move. The move still starts from your old server." +msgstr "이 페이지는 Hackers' Pub 쪽 이전 준비만 합니다. 이전 시작은 예전 서버에서 해야 합니다." + #: src/components/QuoteTargetPlaceholder.tsx:36 msgid "This post quoted another post, but the quote is not currently authorized." msgstr "이 콘텐츠는 다른 콘텐츠를 인용했지만, 현재 인용이 허가되지 않았습니다." @@ -4308,7 +4468,7 @@ msgstr "보통 1분 정도 소요됩니다. 번역이 완료되면 페이지가 msgid "This will be part of the article URL." msgstr "게시글 URL의 일부가 됩니다." -#: src/components/AppSidebar.tsx:167 +#: src/components/AppSidebar.tsx:150 msgid "Timeline" msgstr "타임라인" @@ -4357,9 +4517,9 @@ msgstr "{name}로 번역 중…" msgid "Translating…" msgstr "번역 중…" -#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:379 -#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:402 -#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:411 +#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:391 +#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:414 +#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:423 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/index.tsx:615 msgid "Translation request failed" msgstr "번역 요청 실패" @@ -4383,7 +4543,7 @@ msgid "Try again" msgstr "다시 시도" #. placeholder {0}: props.username -#: src/routes/(root)/[handle]/settings/account.tsx:241 +#: src/routes/(root)/[handle]/settings/account.tsx:560 msgid "Type {0} to confirm account deletion." msgstr "계정 삭제를 확인하려면 {0}을(를) 입력하세요." @@ -4472,10 +4632,14 @@ msgstr "URL" msgid "URL pattern" msgstr "URL 패턴" -#: src/components/AppSidebar.tsx:504 +#: src/components/AppSidebar.tsx:487 msgid "Use old UI" msgstr "예전 UI 사용하기" +#: src/routes/(root)/[handle]/settings/account.tsx:375 +#~ msgid "Use the old account's handle or actor URL." +#~ msgstr "예전 계정의 핸들 또는 액터 URL을 사용하세요." + #: src/components/ProfileActionMenu.tsx:320 msgid "User blocked" msgstr "사용자를 차단했습니다" @@ -4498,7 +4662,7 @@ msgstr "사용자 차단을 해제했습니다" msgid "User unmuted" msgstr "사용자 뮤트를 해제했습니다" -#: src/routes/(root)/[handle]/settings/account.tsx:234 +#: src/routes/(root)/[handle]/settings/account.tsx:552 #: src/routes/(root)/[handle]/settings/index.tsx:423 #: src/routes/(root)/sign/up/[token].tsx:331 msgid "Username" @@ -4538,7 +4702,7 @@ msgstr "{1}에 {0} 님이 이 링크의 소유자임이 확인됨" msgid "Verifying your invitation…" msgstr "초대장을 확인하고 있습니다…" -#: src/components/AppSidebar.tsx:814 +#: src/components/AppSidebar.tsx:797 msgid "View all drafts →" msgstr "모든 초고 보기 →" @@ -4677,7 +4841,7 @@ msgstr "결정 철회" msgid "Withdrawn" msgstr "철회됨" -#: src/components/AppSidebar.tsx:263 +#: src/components/AppSidebar.tsx:246 msgid "Without shares" msgstr "공유 제외" @@ -4740,7 +4904,12 @@ msgstr "이미지는 최대 {MAX_MEDIA}장까지 첨부할 수 있습니다" msgid "You can change it only once, and the old username will become available to others." msgstr "아이디는 단 한 번만 변경할 수 있으며, 변경하기 전 아이디는 다른 사람이 사용할 수 있게 됩니다." -#: src/routes/(root)/[handle]/settings/account.tsx:192 +#: src/routes/(root)/[handle]/settings/account.tsx:280 +#: src/routes/(root)/[handle]/settings/account.tsx:329 +#~ msgid "You can change migration aliases only for your own account." +#~ msgstr "자신의 계정에서만 이전 별칭을 변경할 수 있습니다." + +#: src/routes/(root)/[handle]/settings/account.tsx:510 msgid "You can delete only your own account." msgstr "자신의 계정만 삭제할 수 있습니다." @@ -4769,6 +4938,11 @@ msgstr "자신의 북마크만 볼 수 있습니다" msgid "You can only view your own drafts" msgstr "자신의 초고만 볼 수 있습니다" +#: src/routes/(root)/[handle]/settings/account.tsx:280 +#: src/routes/(root)/[handle]/settings/account.tsx:331 +msgid "You can prepare migration only for your own account." +msgstr "자신의 계정에서만 이전을 준비할 수 있습니다." + #: src/routes/(root)/[handle]/settings/passkeys.tsx:405 msgid "You don't have any passkeys registered yet." msgstr "등록된 패스키가 아직 없습니다." @@ -4856,6 +5030,14 @@ msgstr "Hackers' Pub에 초대되었습니다" msgid "Your account is suspended, so you can't post right now. See your sanctions for details and how to appeal." msgstr "회원님의 계정이 정지되어 지금은 글을 작성할 수 없습니다. 자세한 내용과 이의 제기 방법은 제재 내역에서 확인하세요." +#: src/routes/(root)/[handle]/settings/account.tsx:266 +#~ msgid "Your actor document now includes the previous account." +#~ msgstr "액터 문서에 예전 계정이 포함되었습니다." + +#: src/routes/(root)/[handle]/settings/account.tsx:315 +#~ msgid "Your actor document was updated." +#~ msgstr "액터 문서가 업데이트되었습니다." + #: src/components/ModerationNotificationList.tsx:119 msgid "Your appeal was reviewed." msgstr "회원님의 이의 제기가 검토되었습니다." @@ -4909,7 +5091,7 @@ msgstr "선호 언어가 업데이트되었습니다." msgid "Your profile settings have been updated successfully." msgstr "프로필 설정이 성공적으로 업데이트되었습니다." -#: src/routes/(root)/[handle]/settings/account.tsx:226 +#: src/routes/(root)/[handle]/settings/account.tsx:544 msgid "Your profile, posts, drafts, follows, settings, and login credentials will be removed. Your current username will remain reserved." msgstr "프로필, 콘텐츠, 초고, 팔로, 설정, 로그인 인증 정보가 삭제됩니다. 현재 아이디는 계속 예약됩니다." diff --git a/web-next/src/locales/zh-CN/messages.po b/web-next/src/locales/zh-CN/messages.po index 197c8480d..c6fa60213 100644 --- a/web-next/src/locales/zh-CN/messages.po +++ b/web-next/src/locales/zh-CN/messages.po @@ -113,7 +113,7 @@ msgid "{0, plural, one {Load # more reactor} other {Load # more reactors}}" msgstr "{0, plural, one {加载更多反应者 (#)} other {加载更多反应者 (#)}}" #. placeholder {0}: props.count -#: src/components/AppSidebar.tsx:457 +#: src/components/AppSidebar.tsx:440 msgid "{0, plural, one {Notifications (# unread)} other {Notifications (# unread)}}" msgstr "{0, plural, other {通知(# 条未读)}}" @@ -320,8 +320,8 @@ msgid "{0}'s following" msgstr "{0}的关注" #. placeholder {0}: actor.rawName ?? actor.username -#: src/routes/(root)/[handle]/(profile)/interactions.tsx:103 -#: src/routes/(root)/[handle]/(profile)/interactions.tsx:107 +#: src/routes/(root)/[handle]/(profile)/interactions.tsx:100 +#: src/routes/(root)/[handle]/(profile)/interactions.tsx:104 msgid "{0}'s interactions" msgstr "与{0}的互动" @@ -366,6 +366,10 @@ msgstr "{days} 天" msgid "{HIGH_PRIORITY_REPORT_COUNT}+ reports" msgstr "{HIGH_PRIORITY_REPORT_COUNT} 条及以上举报" +#: src/routes/(root)/[handle]/settings/account.tsx:387 +msgid "@old@example.com or actor URL" +msgstr "@old@example.com 或 actor URL" + #: src/routes/(root)/[handle]/[idOrYear]/[slug]/reactions.tsx:231 #: src/routes/(root)/[handle]/[noteId]/reactions.tsx:253 #~ msgid "+{0} more reactor(s) not shown" @@ -452,12 +456,12 @@ msgid "A user (profile) report." msgstr "用户(资料)举报。" #: src/components/admin/AdminAccountsTable.tsx:224 -#: src/components/AppSidebar.tsx:498 +#: src/components/AppSidebar.tsx:481 #: src/components/SettingsTabs.tsx:112 msgid "Account" msgstr "账户" -#: src/routes/(root)/[handle]/settings/account.tsx:174 +#: src/routes/(root)/[handle]/settings/account.tsx:492 msgid "Account deletion is unavailable" msgstr "账户删除功能不可用" @@ -465,11 +469,15 @@ msgstr "账户删除功能不可用" msgid "Account handle" msgstr "账户用户名" +#: src/routes/(root)/[handle]/settings/account.tsx:185 +msgid "Account migration" +msgstr "账户迁移" + #: src/routes/(root)/[handle]/settings/sanctions.tsx:94 msgid "Account permanently suspended" msgstr "账户已永久封停" -#: src/routes/(root)/[handle]/settings/account.tsx:124 +#: src/routes/(root)/[handle]/settings/account.tsx:179 msgid "Account settings" msgstr "账户设置" @@ -503,6 +511,7 @@ msgstr "激活于" msgid "Actors currently under an active suspension or federation block. Expired suspensions drop off automatically." msgstr "当前处于封停或联邦屏蔽状态的行为者。已过期的封停会自动移除。" +#: src/routes/(root)/[handle]/settings/account.tsx:407 #: src/routes/(root)/[handle]/settings/language.tsx:196 #: src/routes/(root)/admin/news.tsx:639 #: src/routes/(root)/admin/news.tsx:748 @@ -527,10 +536,15 @@ msgstr "添加选项" msgid "Add poll" msgstr "添加投票调查" +#: src/routes/(root)/[handle]/settings/account.tsx:360 +msgid "Add the old account here. Hackers' Pub will publish it as another account that belongs to you." +msgstr "在这里添加旧账户。Hackers' Pub 会将它公开为属于你的另一个账户。" + #: src/components/HashtagActionBar.tsx:258 msgid "Add to sidebar" msgstr "添加到侧边栏" +#: src/routes/(root)/[handle]/settings/account.tsx:407 #: src/routes/(root)/admin/news.tsx:639 #: src/routes/(root)/admin/news.tsx:748 msgid "Adding…" @@ -540,10 +554,18 @@ msgstr "添加中…" msgid "Additional context (optional)" msgstr "补充说明(可选)" -#: src/components/AppSidebar.tsx:649 +#: src/components/AppSidebar.tsx:632 msgid "Admin" msgstr "管理" +#: src/routes/(root)/[handle]/settings/account.tsx:187 +#~ msgid "Advertise previous accounts before starting the move from the old server." +#~ msgstr "从旧服务器开始迁移前,先公开以前的账户。" + +#: src/routes/(root)/[handle]/settings/account.tsx:366 +msgid "After the old server confirms the destination, it sends the Move activity and compatible servers can move followers here." +msgstr "旧服务器确认目标账户后,会发送 Move 活动,兼容的服务器可以把粉丝迁移到这里。" + #: src/routes/(root)/[handle]/bookmarks.tsx:136 #: src/routes/(root)/admin/moderation/appeals.tsx:157 #: src/routes/(root)/admin/moderation/index.tsx:123 @@ -749,7 +771,7 @@ msgstr "文章网址别名" msgid "Articles" msgstr "文章" -#: src/components/AppSidebar.tsx:289 +#: src/components/AppSidebar.tsx:272 #: src/components/ProfileCard.tsx:197 msgid "Articles only" msgstr "仅文章" @@ -841,7 +863,7 @@ msgstr "粗体" msgid "Bookmark" msgstr "收藏" -#: src/components/AppSidebar.tsx:585 +#: src/components/AppSidebar.tsx:568 #: src/routes/(root)/[handle]/bookmarks.tsx:126 msgid "Bookmarks" msgstr "收藏" @@ -907,7 +929,7 @@ msgstr "由 {0} 发布" #: src/components/RemoveFollowerButton.tsx:144 #: src/components/ReportDialog.tsx:224 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/edit.tsx:523 -#: src/routes/(root)/[handle]/settings/account.tsx:269 +#: src/routes/(root)/[handle]/settings/account.tsx:588 #: src/routes/(root)/[handle]/settings/index.tsx:408 #: src/routes/(root)/[handle]/settings/passkeys.tsx:522 #: src/routes/(root)/authorize_interaction.tsx:273 @@ -918,10 +940,15 @@ msgstr "取消" msgid "Cannot change the language because translations already exist" msgstr "由于已存在翻译,无法更改语言" -#: src/routes/(root)/[handle]/settings/account.tsx:191 +#: src/routes/(root)/[handle]/settings/account.tsx:509 msgid "Cannot delete this account" msgstr "无法删除此账户" +#: src/routes/(root)/[handle]/settings/account.tsx:279 +#: src/routes/(root)/[handle]/settings/account.tsx:330 +msgid "Cannot update this account" +msgstr "无法更新此账户" + #: src/components/admin/ModerationSubTabs.tsx:28 msgid "Cases" msgstr "案例" @@ -1001,7 +1028,7 @@ msgstr "已结束" msgid "Code" msgstr "代码" -#: src/components/AppSidebar.tsx:872 +#: src/components/AppSidebar.tsx:855 #: src/routes/(root)/coc.tsx:40 #: src/routes/(root)/sign/up/[token].tsx:458 msgid "Code of conduct" @@ -1016,7 +1043,7 @@ msgstr "行为准则:{0}" #~ msgid "Comments ({0})" #~ msgstr "评论({0})" -#: src/components/AppSidebar.tsx:709 +#: src/components/AppSidebar.tsx:692 #: src/components/FloatingComposeButton.tsx:61 msgid "Compose" msgstr "写作" @@ -1051,6 +1078,16 @@ msgstr "已复制" msgid "Copy" msgstr "复制" +#: src/routes/(root)/[handle]/settings/account.tsx:286 +#: src/routes/(root)/[handle]/settings/account.tsx:292 +#~ msgid "Could not add migration alias" +#~ msgstr "无法添加迁移别名" + +#: src/routes/(root)/[handle]/settings/account.tsx:287 +#: src/routes/(root)/[handle]/settings/account.tsx:293 +msgid "Could not add previous account" +msgstr "无法添加旧账户" + #: src/routes/(root)/[handle]/settings/invite.tsx:638 msgid "Could not copy the link to the clipboard." msgstr "无法将链接复制到剪贴板。" @@ -1073,6 +1110,16 @@ msgstr "无法记录处理" msgid "Could not refresh this from its origin." msgstr "无法从来源刷新此对象。" +#: src/routes/(root)/[handle]/settings/account.tsx:334 +#: src/routes/(root)/[handle]/settings/account.tsx:342 +#~ msgid "Could not remove migration alias" +#~ msgstr "无法移除迁移别名" + +#: src/routes/(root)/[handle]/settings/account.tsx:336 +#: src/routes/(root)/[handle]/settings/account.tsx:344 +msgid "Could not remove previous account" +msgstr "无法移除旧账户" + #: src/routes/(root)/admin/refresh.tsx:129 msgid "Could not resolve that as a remote object." msgstr "无法将其解析为远程对象。" @@ -1096,7 +1143,7 @@ msgstr "无法提交申诉" msgid "Could not vote on this poll" msgstr "无法在此投票调查中投票" -#: src/components/AppSidebar.tsx:754 +#: src/components/AppSidebar.tsx:737 #: src/components/FloatingComposeButton.tsx:123 msgid "Create article" msgstr "创建文章" @@ -1105,7 +1152,7 @@ msgstr "创建文章" msgid "Create invitation link" msgstr "创建邀请链接" -#: src/components/AppSidebar.tsx:731 +#: src/components/AppSidebar.tsx:714 #: src/components/FloatingComposeButton.tsx:99 #: src/components/NoteComposeModal.tsx:78 #: src/components/NoteComposer.tsx:1873 @@ -1191,13 +1238,13 @@ msgstr "默认转帖隐私设置" msgid "Delete" msgstr "删除" -#: src/routes/(root)/[handle]/settings/account.tsx:125 -#: src/routes/(root)/[handle]/settings/account.tsx:253 -#: src/routes/(root)/[handle]/settings/account.tsx:278 +#: src/routes/(root)/[handle]/settings/account.tsx:199 +#: src/routes/(root)/[handle]/settings/account.tsx:572 +#: src/routes/(root)/[handle]/settings/account.tsx:597 msgid "Delete account" msgstr "删除账户" -#: src/routes/(root)/[handle]/settings/account.tsx:261 +#: src/routes/(root)/[handle]/settings/account.tsx:580 msgid "Delete account permanently?" msgstr "要永久删除账户吗?" @@ -1215,7 +1262,7 @@ msgid "Delete post?" msgstr "删除内容?" #: src/components/article-composer/ArticleComposerActions.tsx:21 -#: src/routes/(root)/[handle]/settings/account.tsx:278 +#: src/routes/(root)/[handle]/settings/account.tsx:597 #: src/routes/(root)/[handle]/settings/invite.tsx:745 #: src/routes/(root)/admin/media.tsx:189 msgid "Deleting…" @@ -1360,6 +1407,18 @@ msgstr "已结束" msgid "Ends" msgstr "截止" +#: src/routes/(root)/[handle]/settings/account.tsx:284 +#~ msgid "Enter a valid previous account handle or actor URL." +#~ msgstr "请输入有效的以前账户 handle 或 actor URL。" + +#: src/routes/(root)/[handle]/settings/account.tsx:394 +msgid "Enter the account you are moving from, for example @old@example.com." +msgstr "请输入你要从中迁移的账户,例如 @old@example.com。" + +#: src/routes/(root)/[handle]/settings/account.tsx:285 +msgid "Enter the account you are moving from, such as @old@example.com or its actor URL." +msgstr "请输入你要从中迁移的账户,例如 @old@example.com 或其 actor URL。" + #: src/routes/(root)/[handle]/invite/[id].tsx:284 msgid "Enter your email address below to get started." msgstr "请在下方输入你的电子邮件地址以开始。" @@ -1492,8 +1551,9 @@ msgstr "复制失败" msgid "Failed to create invitation link" msgstr "创建邀请链接失败" -#: src/routes/(root)/[handle]/settings/account.tsx:198 -#: src/routes/(root)/[handle]/settings/account.tsx:209 +#: src/routes/(root)/[handle]/settings/account.tsx:477 +#: src/routes/(root)/[handle]/settings/account.tsx:516 +#: src/routes/(root)/[handle]/settings/account.tsx:527 msgid "Failed to delete account" msgstr "删除账户失败" @@ -1736,7 +1796,7 @@ msgid "Failed to share post" msgstr "转帖失败" #. placeholder {0}: error.message -#: src/components/AppSidebar.tsx:144 +#: src/components/AppSidebar.tsx:127 msgid "Failed to sign out: {0}" msgstr "登出失败:{0}" @@ -1814,7 +1874,7 @@ msgstr "投票失败" msgid "Favor links shared by specific accounts. A preferred sharer's posts count toward the news feed even when the account is a bot (for example a feed that reposts Hacker News links), and the links it shares get a flat promotion bonus in the popular ranking. A penalty on a link overrides the promotion." msgstr "优先展示特定账户转帖的链接。即使账户是机器人(例如转发 Hacker News 链接的订阅源),优先转帖者的内容也会计入新闻订阅流,且其转帖的链接会在热门排名中获得固定的优先加分。对链接的处罚会覆盖该优先。" -#: src/components/AppSidebar.tsx:341 +#: src/components/AppSidebar.tsx:324 msgid "Fediverse" msgstr "联邦宇宙" @@ -1822,7 +1882,7 @@ msgstr "联邦宇宙" msgid "Fediverse handle" msgstr "联邦宇宙用户名" -#: src/components/AppSidebar.tsx:220 +#: src/components/AppSidebar.tsx:203 msgid "Feed" msgstr "订阅流" @@ -1889,7 +1949,7 @@ msgstr "生成中…" msgid "Get browser notifications" msgstr "接收浏览器通知" -#: src/components/AppSidebar.tsx:912 +#: src/components/AppSidebar.tsx:895 msgid "GitHub repository" msgstr "GitHub 仓库" @@ -1927,8 +1987,8 @@ msgstr "向自上次重新发放截止时间以来最活跃的账号(按内容 msgid "Graph" msgstr "关系图" -#: src/components/AppSidebar.tsx:307 -#: src/components/AppSidebar.tsx:429 +#: src/components/AppSidebar.tsx:290 +#: src/components/AppSidebar.tsx:412 #: src/routes/(root).tsx:196 #: src/routes/(root)/coc.tsx:40 #: src/routes/(root)/markdown.tsx:40 @@ -1945,6 +2005,22 @@ msgstr "Hackers' Pub 首页" msgid "Hackers' Pub is a place for software engineers to share their knowledge and experience with each other. It's also an ActivityPub-enabled social network, so you can follow your favorite hackers in the fediverse and get their latest posts in your feed." msgstr "Hackers' Pub 是个为软件工程师共同分享知识和经验的地方。它也是启用了 ActivityPub 的社交网络,这样你可以在联邦宇宙里关注你喜爱的黑客,并获取最新的帖子。" +#: src/routes/(root)/[handle]/settings/account.tsx:317 +#~ msgid "Hackers' Pub no longer publishes that account as an alias." +#~ msgstr "Hackers' Pub 不再将该账户公开为别名。" + +#: src/routes/(root)/[handle]/settings/account.tsx:317 +msgid "Hackers' Pub no longer publishes that account as another account that belongs to you." +msgstr "Hackers' Pub 不再将该账户公开为属于你的另一个账户。" + +#: src/routes/(root)/[handle]/settings/account.tsx:266 +msgid "Hackers' Pub now publishes the old account as another account that belongs to you." +msgstr "Hackers' Pub 现在会将旧账户公开为属于你的另一个账户。" + +#: src/routes/(root)/[handle]/settings/account.tsx:266 +#~ msgid "Hackers' Pub now publishes the old account as belonging to you." +#~ msgstr "Hackers' Pub 现在会公开旧账户属于你。" + #: src/routes/(root)/admin/index.tsx:88 msgid "Hackers' Pub: Admin · Accounts" msgstr "Hackers' Pub:管理 · 账号" @@ -2143,7 +2219,7 @@ msgstr "邀请链接" msgid "Invitation sent" msgstr "邀请已发送" -#: src/components/AppSidebar.tsx:864 +#: src/components/AppSidebar.tsx:847 #: src/routes/(root)/[handle]/settings/invite.tsx:910 #: src/routes/(root)/tree/graph.tsx:79 #: src/routes/(root)/tree/index.tsx:206 @@ -2159,7 +2235,7 @@ msgstr "邀请" msgid "Invitations left" msgstr "剩余邀请" -#: src/components/AppSidebar.tsx:608 +#: src/components/AppSidebar.tsx:591 #: src/components/SettingsTabs.tsx:72 #: src/routes/(root)/[handle]/settings/invite.tsx:311 msgid "Invite" @@ -2517,6 +2593,14 @@ msgstr "只提及用户可见" msgid "Message to the user (optional)" msgstr "给用户的留言(可选)" +#: src/routes/(root)/[handle]/settings/account.tsx:264 +#~ msgid "Migration alias added" +#~ msgstr "迁移别名已添加" + +#: src/routes/(root)/[handle]/settings/account.tsx:314 +#~ msgid "Migration alias removed" +#~ msgstr "迁移别名已移除" + #: src/components/ReportDialog.tsx:192 msgid "Minimum {MIN_REASON_LENGTH} characters required." msgstr "至少需要输入 {MIN_REASON_LENGTH} 个字符。" @@ -2645,7 +2729,7 @@ msgid "Newest" msgstr "最新" #: src/components/AdminTabs.tsx:58 -#: src/components/AppSidebar.tsx:193 +#: src/components/AppSidebar.tsx:176 #: src/routes/(root)/admin/news.tsx:555 #: src/routes/(root)/news/index.tsx:48 msgid "News" @@ -2726,6 +2810,10 @@ msgstr "没有剩余邀请名额" msgid "No matching object found" msgstr "未找到匹配的对象" +#: src/routes/(root)/[handle]/settings/account.tsx:397 +#~ msgid "No migration aliases yet." +#~ msgstr "暂无迁移别名。" + #: src/components/ActorArticleList.tsx:93 msgid "No notes articles" msgstr "未找到文章" @@ -2768,6 +2856,10 @@ msgstr "暂无优先转帖者。" msgid "No previews" msgstr "不显示预览" +#: src/routes/(root)/[handle]/settings/account.tsx:416 +msgid "No previous accounts added yet." +msgstr "暂无已添加的旧账户。" + #: src/routes/(root)/admin/moderation/statistics.tsx:223 msgid "No provisions have been cited yet." msgstr "尚未引用任何条款。" @@ -2884,8 +2976,8 @@ msgstr "未授予通知权限。" msgid "Notification preview privacy" msgstr "通知预览隐私" -#: src/components/AppSidebar.tsx:464 -#: src/components/AppSidebar.tsx:465 +#: src/components/AppSidebar.tsx:447 +#: src/components/AppSidebar.tsx:448 #: src/routes/(root).tsx:214 #: src/routes/(root).tsx:215 msgid "Notifications" @@ -2904,6 +2996,14 @@ msgstr "浏览器设置已屏蔽通知。" msgid "Number of invitations" msgstr "邀请次数" +#: src/routes/(root)/[handle]/settings/account.tsx:381 +msgid "Old account" +msgstr "旧账户" + +#: src/routes/(root)/[handle]/settings/account.tsx:363 +msgid "On the old server, open account migration settings and set this Hackers' Pub account as the new account." +msgstr "在旧服务器上打开账户迁移设置,并将此 Hackers' Pub 账户设置为新账户。" + #: src/components/RefreshFromOriginItem.tsx:79 #: src/routes/(root)/admin/refresh.tsx:136 msgid "Only moderators can refresh remote objects." @@ -3002,7 +3102,7 @@ msgstr "等待审核" msgid "People you might want to follow" msgstr "推荐关注" -#: src/routes/(root)/[handle]/settings/account.tsx:126 +#: src/routes/(root)/[handle]/settings/account.tsx:201 msgid "Permanently delete your account and sign out of this session." msgstr "永久删除你的账户,并退出当前会话。" @@ -3048,7 +3148,17 @@ msgstr "请输入文章标题。" msgid "Please enter your Fediverse handle." msgstr "请输入你的联邦宇宙用户名。" -#: src/routes/(root)/[handle]/settings/account.tsx:184 +#: src/routes/(root)/[handle]/settings/account.tsx:273 +#: src/routes/(root)/[handle]/settings/account.tsx:324 +msgid "Please sign in again before changing account migration settings." +msgstr "请重新登录后再更改账户迁移设置。" + +#: src/routes/(root)/[handle]/settings/account.tsx:273 +#: src/routes/(root)/[handle]/settings/account.tsx:322 +#~ msgid "Please sign in again before changing migration aliases." +#~ msgstr "请重新登录后再更改迁移别名。" + +#: src/routes/(root)/[handle]/settings/account.tsx:502 msgid "Please sign in again before deleting your account." msgstr "删除账户前请重新登录。" @@ -3168,12 +3278,28 @@ msgstr "已移除优先转帖者。" msgid "Preferred sharers" msgstr "优先转帖者" +#: src/routes/(root)/[handle]/settings/account.tsx:187 +msgid "Prepare this account as the destination for a Mastodon-style move." +msgstr "将此账户准备为 Mastodon 式迁移的目标账户。" + #: src/components/article-composer/ArticleComposerForm.tsx:111 #: src/components/MarkdownEditor.tsx:164 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/edit.tsx:427 msgid "Preview" msgstr "预览" +#: src/routes/(root)/[handle]/settings/account.tsx:362 +#~ msgid "Previous account" +#~ msgstr "以前的账户" + +#: src/routes/(root)/[handle]/settings/account.tsx:264 +msgid "Previous account added" +msgstr "旧账户已添加" + +#: src/routes/(root)/[handle]/settings/account.tsx:315 +msgid "Previous account removed" +msgstr "旧账户已移除" + #: src/components/ImageLightbox.tsx:80 msgid "Previous image" msgstr "上一张图片" @@ -3186,7 +3312,7 @@ msgstr "以往违规记录" msgid "Priority" msgstr "优先级" -#: src/components/AppSidebar.tsx:879 +#: src/components/AppSidebar.tsx:862 #: src/routes/(root)/privacy.tsx:40 msgid "Privacy policy" msgstr "隐私政策" @@ -3340,7 +3466,7 @@ msgstr "即使此标签页已关闭,也能立即收到新通知。" msgid "Receive notifications immediately through this browser, even when this tab is closed." msgstr "通过此浏览器立即接收通知,即使此标签页已关闭。" -#: src/components/AppSidebar.tsx:790 +#: src/components/AppSidebar.tsx:773 msgid "Recent drafts" msgstr "最近的草稿" @@ -3447,6 +3573,7 @@ msgid "Remote follow" msgstr "远程关注" #: src/components/LanguageList.tsx:225 +#: src/routes/(root)/[handle]/settings/account.tsx:437 #: src/routes/(root)/admin/news.tsx:669 #: src/routes/(root)/admin/news.tsx:805 msgid "Remove" @@ -3457,6 +3584,10 @@ msgstr "移除" msgid "Remove {0}" msgstr "移除{0}" +#: src/routes/(root)/[handle]/settings/account.tsx:433 +msgid "Remove {alias}" +msgstr "移除 {alias}" + #: src/components/BookmarkButton.tsx:150 #: src/components/BookmarkButton.tsx:151 msgid "Remove bookmark" @@ -3504,6 +3635,10 @@ msgstr "移除引用" msgid "Removes stored media that are old enough and no longer attached to an avatar, note, article draft, or article." msgstr "移除已过期且不再附加到头像、帖子、文章草稿或文章的已存储媒体。" +#: src/routes/(root)/[handle]/settings/account.tsx:437 +msgid "Removing…" +msgstr "正在移除…" + #: src/components/article-composer/ArticleComposerForm.tsx:134 #: src/components/MarkdownEditor.tsx:181 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/edit.tsx:453 @@ -3668,7 +3803,7 @@ msgid "Saving…" msgstr "保存中…" #: src/components/admin/AdminAccountsTable.tsx:202 -#: src/components/AppSidebar.tsx:363 +#: src/components/AppSidebar.tsx:346 #: src/components/SearchForm.tsx:65 #: src/components/SearchForm.tsx:80 #: src/routes/(root)/admin/moderation/index.tsx:192 @@ -3742,7 +3877,7 @@ msgstr "标签之间用空格分隔。标签有助于读者发现您的文章。 msgid "Set your personal preferences." msgstr "设置您的个人偏好设置。" -#: src/components/AppSidebar.tsx:639 +#: src/components/AppSidebar.tsx:622 msgid "Settings" msgstr "设置" @@ -3823,12 +3958,14 @@ msgstr "以管理团队名义向被举报用户显示。" msgid "Shown to the user" msgstr "向用户显示" -#: src/components/AppSidebar.tsx:540 +#: src/components/AppSidebar.tsx:523 #: src/routes/(root)/sign/index.tsx:419 msgid "Sign in" msgstr "登录" -#: src/routes/(root)/[handle]/settings/account.tsx:183 +#: src/routes/(root)/[handle]/settings/account.tsx:272 +#: src/routes/(root)/[handle]/settings/account.tsx:323 +#: src/routes/(root)/[handle]/settings/account.tsx:501 msgid "Sign in required" msgstr "需要登录" @@ -3848,7 +3985,7 @@ msgstr "登录后投票" msgid "Sign in with passkey" msgstr "使用通行密钥登录" -#: src/components/AppSidebar.tsx:851 +#: src/components/AppSidebar.tsx:834 msgid "Sign out" msgstr "登出" @@ -4090,8 +4227,9 @@ msgstr "您转帖的默认隐私设置。" msgid "The default quote permission for your notes." msgstr "帖子的默认引用权限设置。" -#: src/routes/(root)/[handle]/settings/account.tsx:200 -#: src/routes/(root)/[handle]/settings/account.tsx:211 +#: src/routes/(root)/[handle]/settings/account.tsx:479 +#: src/routes/(root)/[handle]/settings/account.tsx:518 +#: src/routes/(root)/[handle]/settings/account.tsx:529 msgid "The deletion request could not be completed. Please try again." msgstr "无法完成删除请求。请重试。" @@ -4136,6 +4274,15 @@ msgstr "邀请链接已成功删除。" msgid "The link to this story is added to your post automatically." msgstr "该话题的链接会自动添加到你的内容中。" +#: src/routes/(root)/[handle]/settings/account.tsx:293 +#~ msgid "The migration alias could not be added. Please try again." +#~ msgstr "无法添加迁移别名。请重试。" + +#: src/routes/(root)/[handle]/settings/account.tsx:335 +#: src/routes/(root)/[handle]/settings/account.tsx:343 +#~ msgid "The migration alias could not be removed. Please try again." +#~ msgstr "无法移除迁移别名。请重试。" + #: src/components/AppealDialog.tsx:103 msgid "The moderation team will review your appeal and notify you." msgstr "管理团队将审核你的申诉并通知你。" @@ -4148,6 +4295,15 @@ msgstr "您访问的页面不存在或已被移动。" msgid "The passkey has been successfully revoked." msgstr "通行密钥已成功撤销。" +#: src/routes/(root)/[handle]/settings/account.tsx:294 +msgid "The previous account could not be added. Please try again." +msgstr "无法添加旧账户。请重试。" + +#: src/routes/(root)/[handle]/settings/account.tsx:337 +#: src/routes/(root)/[handle]/settings/account.tsx:345 +msgid "The previous account could not be removed. Please try again." +msgstr "无法移除旧账户。请重试。" + #: src/components/article-composer/ArticleComposerPublishFields.tsx:60 msgid "The primary language of your article, used for accessibility and discovery." msgstr "文章的主要语言,用于无障碍功能和内容发现。" @@ -4167,7 +4323,7 @@ msgstr "注册链接无效。请确保你使用的是你收到的正确邮件链 #. placeholder {0}: "GITHUB_REPOSITORY" #. placeholder {1}: "AGPL-3.0" -#: src/components/AppSidebar.tsx:903 +#: src/components/AppSidebar.tsx:886 msgid "The source code of this website is available on {0} under the {1} license." msgstr "可在 {0} 上以 {1} 许可获取该网站的源代码。" @@ -4192,7 +4348,7 @@ msgstr "Web Push 公钥无效。" msgid "There are no moderation actions on your account." msgstr "你的账户没有任何审核处理。" -#: src/routes/(root)/[handle]/settings/account.tsx:176 +#: src/routes/(root)/[handle]/settings/account.tsx:494 msgid "This account cannot be deleted right now. Please contact the instance administrators." msgstr "当前无法删除此账户。请联系实例管理员。" @@ -4212,7 +4368,7 @@ msgstr "此账户已被封停。" msgid "This action cannot be undone. This will permanently delete this post." msgstr "此操作无法撤销。这将永久删除该内容。" -#: src/routes/(root)/[handle]/settings/account.tsx:223 +#: src/routes/(root)/[handle]/settings/account.tsx:541 msgid "This action is permanent." msgstr "此操作无法撤销。" @@ -4221,7 +4377,7 @@ msgstr "此操作无法撤销。" msgid "This browser does not support Web Push." msgstr "此浏览器不支持 Web Push。" -#: src/routes/(root)/[handle]/settings/account.tsx:264 +#: src/routes/(root)/[handle]/settings/account.tsx:583 msgid "This cannot be undone. Your account will be deleted and you will be signed out." msgstr "此操作无法撤销。你的账户将被删除,并且你会被登出。" @@ -4264,6 +4420,10 @@ msgstr "这是没有本地通知或申诉的远程行为者。警告仅作记录 msgid "This is too long (maximum {MAX_REASON_LENGTH} characters)." msgstr "内容过长(最多 {MAX_REASON_LENGTH} 个字符)。" +#: src/routes/(root)/[handle]/settings/account.tsx:356 +msgid "This page only prepares the Hackers' Pub side of the move. The move still starts from your old server." +msgstr "此页面只准备 Hackers' Pub 这边的迁移。迁移仍需从旧服务器开始。" + #: src/components/QuoteTargetPlaceholder.tsx:36 msgid "This post quoted another post, but the quote is not currently authorized." msgstr "此内容引用了另一则内容,但当前未获得引用授权。" @@ -4308,7 +4468,7 @@ msgstr "通常需要一分钟左右。翻译完成后页面将自动更新。" msgid "This will be part of the article URL." msgstr "这将成为文章 URL 的一部分。" -#: src/components/AppSidebar.tsx:167 +#: src/components/AppSidebar.tsx:150 msgid "Timeline" msgstr "时间线" @@ -4357,9 +4517,9 @@ msgstr "正在翻译为{name}…" msgid "Translating…" msgstr "正在翻译…" -#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:379 -#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:402 -#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:411 +#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:391 +#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:414 +#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:423 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/index.tsx:615 msgid "Translation request failed" msgstr "翻译请求失败" @@ -4383,7 +4543,7 @@ msgid "Try again" msgstr "重试" #. placeholder {0}: props.username -#: src/routes/(root)/[handle]/settings/account.tsx:241 +#: src/routes/(root)/[handle]/settings/account.tsx:560 msgid "Type {0} to confirm account deletion." msgstr "请输入{0}以确认账户删除。" @@ -4472,10 +4632,14 @@ msgstr "URL" msgid "URL pattern" msgstr "URL 模式" -#: src/components/AppSidebar.tsx:504 +#: src/components/AppSidebar.tsx:487 msgid "Use old UI" msgstr "使用旧版界面" +#: src/routes/(root)/[handle]/settings/account.tsx:375 +#~ msgid "Use the old account's handle or actor URL." +#~ msgstr "使用旧账户的 handle 或 actor URL。" + #: src/components/ProfileActionMenu.tsx:320 msgid "User blocked" msgstr "已屏蔽用户" @@ -4498,7 +4662,7 @@ msgstr "已取消屏蔽用户" msgid "User unmuted" msgstr "已取消隐藏用户" -#: src/routes/(root)/[handle]/settings/account.tsx:234 +#: src/routes/(root)/[handle]/settings/account.tsx:552 #: src/routes/(root)/[handle]/settings/index.tsx:423 #: src/routes/(root)/sign/up/[token].tsx:331 msgid "Username" @@ -4538,7 +4702,7 @@ msgstr "已于{1}验证此链接归{0}所有" msgid "Verifying your invitation…" msgstr "正在验证您的邀请…" -#: src/components/AppSidebar.tsx:814 +#: src/components/AppSidebar.tsx:797 msgid "View all drafts →" msgstr "查看所有草稿 →" @@ -4677,7 +4841,7 @@ msgstr "撤销决定" msgid "Withdrawn" msgstr "已撤销" -#: src/components/AppSidebar.tsx:263 +#: src/components/AppSidebar.tsx:246 msgid "Without shares" msgstr "不含转帖" @@ -4740,7 +4904,12 @@ msgstr "最多可附加 {MAX_MEDIA} 张图片" msgid "You can change it only once, and the old username will become available to others." msgstr "你只能更改一次用户名,而旧的用户名会公开为别人使用。" -#: src/routes/(root)/[handle]/settings/account.tsx:192 +#: src/routes/(root)/[handle]/settings/account.tsx:280 +#: src/routes/(root)/[handle]/settings/account.tsx:329 +#~ msgid "You can change migration aliases only for your own account." +#~ msgstr "你只能更改自己账户的迁移别名。" + +#: src/routes/(root)/[handle]/settings/account.tsx:510 msgid "You can delete only your own account." msgstr "你只能删除自己的账户。" @@ -4769,6 +4938,11 @@ msgstr "您只能查看自己的收藏" msgid "You can only view your own drafts" msgstr "您只能查看自己的草稿" +#: src/routes/(root)/[handle]/settings/account.tsx:280 +#: src/routes/(root)/[handle]/settings/account.tsx:331 +msgid "You can prepare migration only for your own account." +msgstr "你只能为自己的账户准备迁移。" + #: src/routes/(root)/[handle]/settings/passkeys.tsx:405 msgid "You don't have any passkeys registered yet." msgstr "您尚未注册任何通行密钥。" @@ -4856,6 +5030,14 @@ msgstr "你被邀请加入 Hackers' Pub" msgid "Your account is suspended, so you can't post right now. See your sanctions for details and how to appeal." msgstr "你的账户已被封停,目前无法发帖。详情及申诉方法请查看处罚记录。" +#: src/routes/(root)/[handle]/settings/account.tsx:266 +#~ msgid "Your actor document now includes the previous account." +#~ msgstr "你的 actor 文档现在包含以前的账户。" + +#: src/routes/(root)/[handle]/settings/account.tsx:315 +#~ msgid "Your actor document was updated." +#~ msgstr "你的 actor 文档已更新。" + #: src/components/ModerationNotificationList.tsx:119 msgid "Your appeal was reviewed." msgstr "你的申诉已审核。" @@ -4909,7 +5091,7 @@ msgstr "您的偏好语言已更新。" msgid "Your profile settings have been updated successfully." msgstr "个人资料设置已成功更新。" -#: src/routes/(root)/[handle]/settings/account.tsx:226 +#: src/routes/(root)/[handle]/settings/account.tsx:544 msgid "Your profile, posts, drafts, follows, settings, and login credentials will be removed. Your current username will remain reserved." msgstr "你的个人资料、内容、草稿、关注关系、设置和登录凭据将被移除。当前用户名将继续保留。" diff --git a/web-next/src/locales/zh-TW/messages.po b/web-next/src/locales/zh-TW/messages.po index 5d8e75490..8fec86d3c 100644 --- a/web-next/src/locales/zh-TW/messages.po +++ b/web-next/src/locales/zh-TW/messages.po @@ -113,7 +113,7 @@ msgid "{0, plural, one {Load # more reactor} other {Load # more reactors}}" msgstr "{0, plural, one {載入更多反應者 (#)} other {載入更多反應者 (#)}}" #. placeholder {0}: props.count -#: src/components/AppSidebar.tsx:457 +#: src/components/AppSidebar.tsx:440 msgid "{0, plural, one {Notifications (# unread)} other {Notifications (# unread)}}" msgstr "{0, plural, other {通知(# 則未讀)}}" @@ -320,8 +320,8 @@ msgid "{0}'s following" msgstr "{0}的關注" #. placeholder {0}: actor.rawName ?? actor.username -#: src/routes/(root)/[handle]/(profile)/interactions.tsx:103 -#: src/routes/(root)/[handle]/(profile)/interactions.tsx:107 +#: src/routes/(root)/[handle]/(profile)/interactions.tsx:100 +#: src/routes/(root)/[handle]/(profile)/interactions.tsx:104 msgid "{0}'s interactions" msgstr "與{0}的互動" @@ -366,6 +366,10 @@ msgstr "{days} 天" msgid "{HIGH_PRIORITY_REPORT_COUNT}+ reports" msgstr "{HIGH_PRIORITY_REPORT_COUNT} 則以上檢舉" +#: src/routes/(root)/[handle]/settings/account.tsx:387 +msgid "@old@example.com or actor URL" +msgstr "@old@example.com 或 actor URL" + #: src/routes/(root)/[handle]/[idOrYear]/[slug]/reactions.tsx:231 #: src/routes/(root)/[handle]/[noteId]/reactions.tsx:253 #~ msgid "+{0} more reactor(s) not shown" @@ -452,12 +456,12 @@ msgid "A user (profile) report." msgstr "使用者(個人檔案)檢舉。" #: src/components/admin/AdminAccountsTable.tsx:224 -#: src/components/AppSidebar.tsx:498 +#: src/components/AppSidebar.tsx:481 #: src/components/SettingsTabs.tsx:112 msgid "Account" msgstr "帳戶" -#: src/routes/(root)/[handle]/settings/account.tsx:174 +#: src/routes/(root)/[handle]/settings/account.tsx:492 msgid "Account deletion is unavailable" msgstr "帳戶刪除功能無法使用" @@ -465,11 +469,15 @@ msgstr "帳戶刪除功能無法使用" msgid "Account handle" msgstr "帳號使用者名稱" +#: src/routes/(root)/[handle]/settings/account.tsx:185 +msgid "Account migration" +msgstr "帳戶遷移" + #: src/routes/(root)/[handle]/settings/sanctions.tsx:94 msgid "Account permanently suspended" msgstr "帳戶已永久停權" -#: src/routes/(root)/[handle]/settings/account.tsx:124 +#: src/routes/(root)/[handle]/settings/account.tsx:179 msgid "Account settings" msgstr "帳戶設定" @@ -503,6 +511,7 @@ msgstr "啟用於" msgid "Actors currently under an active suspension or federation block. Expired suspensions drop off automatically." msgstr "目前處於停權或聯邦封鎖狀態的行為者。已過期的停權會自動移除。" +#: src/routes/(root)/[handle]/settings/account.tsx:407 #: src/routes/(root)/[handle]/settings/language.tsx:196 #: src/routes/(root)/admin/news.tsx:639 #: src/routes/(root)/admin/news.tsx:748 @@ -527,10 +536,15 @@ msgstr "新增選項" msgid "Add poll" msgstr "新增投票調查" +#: src/routes/(root)/[handle]/settings/account.tsx:360 +msgid "Add the old account here. Hackers' Pub will publish it as another account that belongs to you." +msgstr "在這裡新增舊帳戶。Hackers' Pub 會將它公開為屬於你的另一個帳戶。" + #: src/components/HashtagActionBar.tsx:258 msgid "Add to sidebar" msgstr "新增至側邊欄" +#: src/routes/(root)/[handle]/settings/account.tsx:407 #: src/routes/(root)/admin/news.tsx:639 #: src/routes/(root)/admin/news.tsx:748 msgid "Adding…" @@ -540,10 +554,18 @@ msgstr "新增中…" msgid "Additional context (optional)" msgstr "補充說明(選填)" -#: src/components/AppSidebar.tsx:649 +#: src/components/AppSidebar.tsx:632 msgid "Admin" msgstr "管理" +#: src/routes/(root)/[handle]/settings/account.tsx:187 +#~ msgid "Advertise previous accounts before starting the move from the old server." +#~ msgstr "從舊伺服器開始遷移前,先公開以前的帳戶。" + +#: src/routes/(root)/[handle]/settings/account.tsx:366 +msgid "After the old server confirms the destination, it sends the Move activity and compatible servers can move followers here." +msgstr "舊伺服器確認目標帳戶後,會傳送 Move 活動,相容的伺服器可以把粉絲遷移到這裡。" + #: src/routes/(root)/[handle]/bookmarks.tsx:136 #: src/routes/(root)/admin/moderation/appeals.tsx:157 #: src/routes/(root)/admin/moderation/index.tsx:123 @@ -749,7 +771,7 @@ msgstr "文章網址別名" msgid "Articles" msgstr "文章" -#: src/components/AppSidebar.tsx:289 +#: src/components/AppSidebar.tsx:272 #: src/components/ProfileCard.tsx:197 msgid "Articles only" msgstr "僅文章" @@ -841,7 +863,7 @@ msgstr "粗體" msgid "Bookmark" msgstr "收藏" -#: src/components/AppSidebar.tsx:585 +#: src/components/AppSidebar.tsx:568 #: src/routes/(root)/[handle]/bookmarks.tsx:126 msgid "Bookmarks" msgstr "收藏" @@ -907,7 +929,7 @@ msgstr "由 {0} 發佈" #: src/components/RemoveFollowerButton.tsx:144 #: src/components/ReportDialog.tsx:224 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/edit.tsx:523 -#: src/routes/(root)/[handle]/settings/account.tsx:269 +#: src/routes/(root)/[handle]/settings/account.tsx:588 #: src/routes/(root)/[handle]/settings/index.tsx:408 #: src/routes/(root)/[handle]/settings/passkeys.tsx:522 #: src/routes/(root)/authorize_interaction.tsx:273 @@ -918,10 +940,15 @@ msgstr "取消" msgid "Cannot change the language because translations already exist" msgstr "由於已存在翻譯,無法變更語言" -#: src/routes/(root)/[handle]/settings/account.tsx:191 +#: src/routes/(root)/[handle]/settings/account.tsx:509 msgid "Cannot delete this account" msgstr "無法刪除此帳戶" +#: src/routes/(root)/[handle]/settings/account.tsx:279 +#: src/routes/(root)/[handle]/settings/account.tsx:330 +msgid "Cannot update this account" +msgstr "無法更新此帳戶" + #: src/components/admin/ModerationSubTabs.tsx:28 msgid "Cases" msgstr "案件" @@ -1001,7 +1028,7 @@ msgstr "已結束" msgid "Code" msgstr "程式碼" -#: src/components/AppSidebar.tsx:872 +#: src/components/AppSidebar.tsx:855 #: src/routes/(root)/coc.tsx:40 #: src/routes/(root)/sign/up/[token].tsx:458 msgid "Code of conduct" @@ -1016,7 +1043,7 @@ msgstr "行為準則:{0}" #~ msgid "Comments ({0})" #~ msgstr "評論({0})" -#: src/components/AppSidebar.tsx:709 +#: src/components/AppSidebar.tsx:692 #: src/components/FloatingComposeButton.tsx:61 msgid "Compose" msgstr "寫作" @@ -1051,6 +1078,16 @@ msgstr "已複製" msgid "Copy" msgstr "複製" +#: src/routes/(root)/[handle]/settings/account.tsx:286 +#: src/routes/(root)/[handle]/settings/account.tsx:292 +#~ msgid "Could not add migration alias" +#~ msgstr "無法新增遷移別名" + +#: src/routes/(root)/[handle]/settings/account.tsx:287 +#: src/routes/(root)/[handle]/settings/account.tsx:293 +msgid "Could not add previous account" +msgstr "無法新增舊帳戶" + #: src/routes/(root)/[handle]/settings/invite.tsx:638 msgid "Could not copy the link to the clipboard." msgstr "無法將連結複製到剪貼簿。" @@ -1073,6 +1110,16 @@ msgstr "無法記錄處置" msgid "Could not refresh this from its origin." msgstr "無法從來源重新整理此物件。" +#: src/routes/(root)/[handle]/settings/account.tsx:334 +#: src/routes/(root)/[handle]/settings/account.tsx:342 +#~ msgid "Could not remove migration alias" +#~ msgstr "無法移除遷移別名" + +#: src/routes/(root)/[handle]/settings/account.tsx:336 +#: src/routes/(root)/[handle]/settings/account.tsx:344 +msgid "Could not remove previous account" +msgstr "無法移除舊帳戶" + #: src/routes/(root)/admin/refresh.tsx:129 msgid "Could not resolve that as a remote object." msgstr "無法將其解析為遠端物件。" @@ -1096,7 +1143,7 @@ msgstr "無法提交申訴" msgid "Could not vote on this poll" msgstr "無法在此投票調查中投票" -#: src/components/AppSidebar.tsx:754 +#: src/components/AppSidebar.tsx:737 #: src/components/FloatingComposeButton.tsx:123 msgid "Create article" msgstr "建立文章" @@ -1105,7 +1152,7 @@ msgstr "建立文章" msgid "Create invitation link" msgstr "建立邀請連結" -#: src/components/AppSidebar.tsx:731 +#: src/components/AppSidebar.tsx:714 #: src/components/FloatingComposeButton.tsx:99 #: src/components/NoteComposeModal.tsx:78 #: src/components/NoteComposer.tsx:1873 @@ -1191,13 +1238,13 @@ msgstr "預設轉貼隱私設定" msgid "Delete" msgstr "刪除" -#: src/routes/(root)/[handle]/settings/account.tsx:125 -#: src/routes/(root)/[handle]/settings/account.tsx:253 -#: src/routes/(root)/[handle]/settings/account.tsx:278 +#: src/routes/(root)/[handle]/settings/account.tsx:199 +#: src/routes/(root)/[handle]/settings/account.tsx:572 +#: src/routes/(root)/[handle]/settings/account.tsx:597 msgid "Delete account" msgstr "刪除帳戶" -#: src/routes/(root)/[handle]/settings/account.tsx:261 +#: src/routes/(root)/[handle]/settings/account.tsx:580 msgid "Delete account permanently?" msgstr "要永久刪除帳戶嗎?" @@ -1215,7 +1262,7 @@ msgid "Delete post?" msgstr "刪除內容?" #: src/components/article-composer/ArticleComposerActions.tsx:21 -#: src/routes/(root)/[handle]/settings/account.tsx:278 +#: src/routes/(root)/[handle]/settings/account.tsx:597 #: src/routes/(root)/[handle]/settings/invite.tsx:745 #: src/routes/(root)/admin/media.tsx:189 msgid "Deleting…" @@ -1360,6 +1407,18 @@ msgstr "已結束" msgid "Ends" msgstr "截止" +#: src/routes/(root)/[handle]/settings/account.tsx:284 +#~ msgid "Enter a valid previous account handle or actor URL." +#~ msgstr "請輸入有效的以前帳戶識別碼或 actor URL。" + +#: src/routes/(root)/[handle]/settings/account.tsx:394 +msgid "Enter the account you are moving from, for example @old@example.com." +msgstr "請輸入你要從中遷移的帳戶,例如 @old@example.com。" + +#: src/routes/(root)/[handle]/settings/account.tsx:285 +msgid "Enter the account you are moving from, such as @old@example.com or its actor URL." +msgstr "請輸入你要從中遷移的帳戶,例如 @old@example.com 或其 actor URL。" + #: src/routes/(root)/[handle]/invite/[id].tsx:284 msgid "Enter your email address below to get started." msgstr "請在下方輸入你的電子郵件地址以開始。" @@ -1492,8 +1551,9 @@ msgstr "複製失敗" msgid "Failed to create invitation link" msgstr "建立邀請連結失敗" -#: src/routes/(root)/[handle]/settings/account.tsx:198 -#: src/routes/(root)/[handle]/settings/account.tsx:209 +#: src/routes/(root)/[handle]/settings/account.tsx:477 +#: src/routes/(root)/[handle]/settings/account.tsx:516 +#: src/routes/(root)/[handle]/settings/account.tsx:527 msgid "Failed to delete account" msgstr "刪除帳戶失敗" @@ -1736,7 +1796,7 @@ msgid "Failed to share post" msgstr "轉貼失敗" #. placeholder {0}: error.message -#: src/components/AppSidebar.tsx:144 +#: src/components/AppSidebar.tsx:127 msgid "Failed to sign out: {0}" msgstr "登出失敗:{0}" @@ -1814,7 +1874,7 @@ msgstr "投票失敗" msgid "Favor links shared by specific accounts. A preferred sharer's posts count toward the news feed even when the account is a bot (for example a feed that reposts Hacker News links), and the links it shares get a flat promotion bonus in the popular ranking. A penalty on a link overrides the promotion." msgstr "優先顯示特定帳號轉貼的連結。即使帳號是機器人(例如轉發 Hacker News 連結的訂閱源),優先轉貼者的內容也會計入新聞訂閱流,且其轉貼的連結會在熱門排名中獲得固定的優先加分。對連結的處罰會覆蓋該優先。" -#: src/components/AppSidebar.tsx:341 +#: src/components/AppSidebar.tsx:324 msgid "Fediverse" msgstr "聯邦宇宙" @@ -1822,7 +1882,7 @@ msgstr "聯邦宇宙" msgid "Fediverse handle" msgstr "聯邦宇宙使用者名稱" -#: src/components/AppSidebar.tsx:220 +#: src/components/AppSidebar.tsx:203 msgid "Feed" msgstr "訂閱流" @@ -1889,7 +1949,7 @@ msgstr "生成中…" msgid "Get browser notifications" msgstr "接收瀏覽器通知" -#: src/components/AppSidebar.tsx:912 +#: src/components/AppSidebar.tsx:895 msgid "GitHub repository" msgstr "GitHub 儲存庫" @@ -1927,8 +1987,8 @@ msgstr "向自上次重新發放截止時間以來最活躍的帳號(按內容 msgid "Graph" msgstr "關係圖" -#: src/components/AppSidebar.tsx:307 -#: src/components/AppSidebar.tsx:429 +#: src/components/AppSidebar.tsx:290 +#: src/components/AppSidebar.tsx:412 #: src/routes/(root).tsx:196 #: src/routes/(root)/coc.tsx:40 #: src/routes/(root)/markdown.tsx:40 @@ -1945,6 +2005,22 @@ msgstr "Hackers' Pub 首頁" msgid "Hackers' Pub is a place for software engineers to share their knowledge and experience with each other. It's also an ActivityPub-enabled social network, so you can follow your favorite hackers in the fediverse and get their latest posts in your feed." msgstr "Hackers' Pub 是個為軟體工程師共同分享知識和經驗的地方。它也是啟用了 ActivityPub 的社交網路,這樣你可以在聯邦宇宙裡關注你喜愛的駭客,並獲取最新的貼文。" +#: src/routes/(root)/[handle]/settings/account.tsx:317 +#~ msgid "Hackers' Pub no longer publishes that account as an alias." +#~ msgstr "Hackers' Pub 不再將該帳戶公開為別名。" + +#: src/routes/(root)/[handle]/settings/account.tsx:317 +msgid "Hackers' Pub no longer publishes that account as another account that belongs to you." +msgstr "Hackers' Pub 不再將該帳戶公開為屬於你的另一個帳戶。" + +#: src/routes/(root)/[handle]/settings/account.tsx:266 +msgid "Hackers' Pub now publishes the old account as another account that belongs to you." +msgstr "Hackers' Pub 現在會將舊帳戶公開為屬於你的另一個帳戶。" + +#: src/routes/(root)/[handle]/settings/account.tsx:266 +#~ msgid "Hackers' Pub now publishes the old account as belonging to you." +#~ msgstr "Hackers' Pub 現在會公開舊帳戶屬於你。" + #: src/routes/(root)/admin/index.tsx:88 msgid "Hackers' Pub: Admin · Accounts" msgstr "Hackers' Pub:管理 · 帳號" @@ -2143,7 +2219,7 @@ msgstr "邀請連結" msgid "Invitation sent" msgstr "邀請已發送" -#: src/components/AppSidebar.tsx:864 +#: src/components/AppSidebar.tsx:847 #: src/routes/(root)/[handle]/settings/invite.tsx:910 #: src/routes/(root)/tree/graph.tsx:79 #: src/routes/(root)/tree/index.tsx:206 @@ -2159,7 +2235,7 @@ msgstr "邀請" msgid "Invitations left" msgstr "剩餘邀請" -#: src/components/AppSidebar.tsx:608 +#: src/components/AppSidebar.tsx:591 #: src/components/SettingsTabs.tsx:72 #: src/routes/(root)/[handle]/settings/invite.tsx:311 msgid "Invite" @@ -2517,6 +2593,14 @@ msgstr "只提及使用者可見" msgid "Message to the user (optional)" msgstr "給使用者的訊息(選填)" +#: src/routes/(root)/[handle]/settings/account.tsx:264 +#~ msgid "Migration alias added" +#~ msgstr "遷移別名已新增" + +#: src/routes/(root)/[handle]/settings/account.tsx:314 +#~ msgid "Migration alias removed" +#~ msgstr "遷移別名已移除" + #: src/components/ReportDialog.tsx:192 msgid "Minimum {MIN_REASON_LENGTH} characters required." msgstr "至少需要輸入 {MIN_REASON_LENGTH} 個字元。" @@ -2645,7 +2729,7 @@ msgid "Newest" msgstr "最新" #: src/components/AdminTabs.tsx:58 -#: src/components/AppSidebar.tsx:193 +#: src/components/AppSidebar.tsx:176 #: src/routes/(root)/admin/news.tsx:555 #: src/routes/(root)/news/index.tsx:48 msgid "News" @@ -2726,6 +2810,10 @@ msgstr "沒有剩餘邀請名額" msgid "No matching object found" msgstr "找不到相符的物件" +#: src/routes/(root)/[handle]/settings/account.tsx:397 +#~ msgid "No migration aliases yet." +#~ msgstr "暫無遷移別名。" + #: src/components/ActorArticleList.tsx:93 msgid "No notes articles" msgstr "未找到文章" @@ -2768,6 +2856,10 @@ msgstr "尚無優先轉貼者。" msgid "No previews" msgstr "不顯示預覽" +#: src/routes/(root)/[handle]/settings/account.tsx:416 +msgid "No previous accounts added yet." +msgstr "暫無已新增的舊帳戶。" + #: src/routes/(root)/admin/moderation/statistics.tsx:223 msgid "No provisions have been cited yet." msgstr "尚未引用任何條款。" @@ -2884,8 +2976,8 @@ msgstr "未授予通知權限。" msgid "Notification preview privacy" msgstr "通知預覽隱私" -#: src/components/AppSidebar.tsx:464 -#: src/components/AppSidebar.tsx:465 +#: src/components/AppSidebar.tsx:447 +#: src/components/AppSidebar.tsx:448 #: src/routes/(root).tsx:214 #: src/routes/(root).tsx:215 msgid "Notifications" @@ -2904,6 +2996,14 @@ msgstr "瀏覽器設定已封鎖通知。" msgid "Number of invitations" msgstr "邀請次數" +#: src/routes/(root)/[handle]/settings/account.tsx:381 +msgid "Old account" +msgstr "舊帳戶" + +#: src/routes/(root)/[handle]/settings/account.tsx:363 +msgid "On the old server, open account migration settings and set this Hackers' Pub account as the new account." +msgstr "在舊伺服器上開啟帳戶遷移設定,並將此 Hackers' Pub 帳戶設為新帳戶。" + #: src/components/RefreshFromOriginItem.tsx:79 #: src/routes/(root)/admin/refresh.tsx:136 msgid "Only moderators can refresh remote objects." @@ -3002,7 +3102,7 @@ msgstr "等待審核" msgid "People you might want to follow" msgstr "推薦關注" -#: src/routes/(root)/[handle]/settings/account.tsx:126 +#: src/routes/(root)/[handle]/settings/account.tsx:201 msgid "Permanently delete your account and sign out of this session." msgstr "永久刪除你的帳戶,並登出此工作階段。" @@ -3048,7 +3148,17 @@ msgstr "請輸入文章標題。" msgid "Please enter your Fediverse handle." msgstr "請輸入你的聯邦宇宙使用者名稱。" -#: src/routes/(root)/[handle]/settings/account.tsx:184 +#: src/routes/(root)/[handle]/settings/account.tsx:273 +#: src/routes/(root)/[handle]/settings/account.tsx:324 +msgid "Please sign in again before changing account migration settings." +msgstr "請重新登入後再變更帳戶遷移設定。" + +#: src/routes/(root)/[handle]/settings/account.tsx:273 +#: src/routes/(root)/[handle]/settings/account.tsx:322 +#~ msgid "Please sign in again before changing migration aliases." +#~ msgstr "請重新登入後再變更遷移別名。" + +#: src/routes/(root)/[handle]/settings/account.tsx:502 msgid "Please sign in again before deleting your account." msgstr "刪除帳戶前請重新登入。" @@ -3168,12 +3278,28 @@ msgstr "已移除優先轉貼者。" msgid "Preferred sharers" msgstr "優先轉貼者" +#: src/routes/(root)/[handle]/settings/account.tsx:187 +msgid "Prepare this account as the destination for a Mastodon-style move." +msgstr "將此帳戶準備為 Mastodon 式遷移的目標帳戶。" + #: src/components/article-composer/ArticleComposerForm.tsx:111 #: src/components/MarkdownEditor.tsx:164 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/edit.tsx:427 msgid "Preview" msgstr "預覽" +#: src/routes/(root)/[handle]/settings/account.tsx:362 +#~ msgid "Previous account" +#~ msgstr "以前的帳戶" + +#: src/routes/(root)/[handle]/settings/account.tsx:264 +msgid "Previous account added" +msgstr "舊帳戶已新增" + +#: src/routes/(root)/[handle]/settings/account.tsx:315 +msgid "Previous account removed" +msgstr "舊帳戶已移除" + #: src/components/ImageLightbox.tsx:80 msgid "Previous image" msgstr "上一張圖片" @@ -3186,7 +3312,7 @@ msgstr "過往違規紀錄" msgid "Priority" msgstr "優先級" -#: src/components/AppSidebar.tsx:879 +#: src/components/AppSidebar.tsx:862 #: src/routes/(root)/privacy.tsx:40 msgid "Privacy policy" msgstr "隱私權政策" @@ -3340,7 +3466,7 @@ msgstr "即使此分頁已關閉,也能立即收到新通知。" msgid "Receive notifications immediately through this browser, even when this tab is closed." msgstr "透過此瀏覽器立即接收通知,即使此分頁已關閉。" -#: src/components/AppSidebar.tsx:790 +#: src/components/AppSidebar.tsx:773 msgid "Recent drafts" msgstr "最近的草稿" @@ -3447,6 +3573,7 @@ msgid "Remote follow" msgstr "遠端關注" #: src/components/LanguageList.tsx:225 +#: src/routes/(root)/[handle]/settings/account.tsx:437 #: src/routes/(root)/admin/news.tsx:669 #: src/routes/(root)/admin/news.tsx:805 msgid "Remove" @@ -3457,6 +3584,10 @@ msgstr "移除" msgid "Remove {0}" msgstr "移除{0}" +#: src/routes/(root)/[handle]/settings/account.tsx:433 +msgid "Remove {alias}" +msgstr "移除 {alias}" + #: src/components/BookmarkButton.tsx:150 #: src/components/BookmarkButton.tsx:151 msgid "Remove bookmark" @@ -3504,6 +3635,10 @@ msgstr "移除引用" msgid "Removes stored media that are old enough and no longer attached to an avatar, note, article draft, or article." msgstr "移除已足夠舊且不再附加到頭像、貼文、文章草稿或文章的已儲存媒體。" +#: src/routes/(root)/[handle]/settings/account.tsx:437 +msgid "Removing…" +msgstr "正在移除…" + #: src/components/article-composer/ArticleComposerForm.tsx:134 #: src/components/MarkdownEditor.tsx:181 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/edit.tsx:453 @@ -3668,7 +3803,7 @@ msgid "Saving…" msgstr "儲存中…" #: src/components/admin/AdminAccountsTable.tsx:202 -#: src/components/AppSidebar.tsx:363 +#: src/components/AppSidebar.tsx:346 #: src/components/SearchForm.tsx:65 #: src/components/SearchForm.tsx:80 #: src/routes/(root)/admin/moderation/index.tsx:192 @@ -3742,7 +3877,7 @@ msgstr "標籤之間用空格分隔。標籤有助於讀者發現您的文章。 msgid "Set your personal preferences." msgstr "設定您的個人偏好設定。" -#: src/components/AppSidebar.tsx:639 +#: src/components/AppSidebar.tsx:622 msgid "Settings" msgstr "設定" @@ -3823,12 +3958,14 @@ msgstr "以管理團隊名義向被檢舉使用者顯示。" msgid "Shown to the user" msgstr "向使用者顯示" -#: src/components/AppSidebar.tsx:540 +#: src/components/AppSidebar.tsx:523 #: src/routes/(root)/sign/index.tsx:419 msgid "Sign in" msgstr "登入" -#: src/routes/(root)/[handle]/settings/account.tsx:183 +#: src/routes/(root)/[handle]/settings/account.tsx:272 +#: src/routes/(root)/[handle]/settings/account.tsx:323 +#: src/routes/(root)/[handle]/settings/account.tsx:501 msgid "Sign in required" msgstr "需要登入" @@ -3848,7 +3985,7 @@ msgstr "登入後投票" msgid "Sign in with passkey" msgstr "使用通行金鑰登入" -#: src/components/AppSidebar.tsx:851 +#: src/components/AppSidebar.tsx:834 msgid "Sign out" msgstr "登出" @@ -4090,8 +4227,9 @@ msgstr "您轉貼的預設隱私設定。" msgid "The default quote permission for your notes." msgstr "貼文的預設引用權限設定。" -#: src/routes/(root)/[handle]/settings/account.tsx:200 -#: src/routes/(root)/[handle]/settings/account.tsx:211 +#: src/routes/(root)/[handle]/settings/account.tsx:479 +#: src/routes/(root)/[handle]/settings/account.tsx:518 +#: src/routes/(root)/[handle]/settings/account.tsx:529 msgid "The deletion request could not be completed. Please try again." msgstr "無法完成刪除請求。請重試。" @@ -4136,6 +4274,15 @@ msgstr "邀請連結已成功刪除。" msgid "The link to this story is added to your post automatically." msgstr "這個話題的連結會自動加入你的內容中。" +#: src/routes/(root)/[handle]/settings/account.tsx:293 +#~ msgid "The migration alias could not be added. Please try again." +#~ msgstr "無法新增遷移別名。請再試一次。" + +#: src/routes/(root)/[handle]/settings/account.tsx:335 +#: src/routes/(root)/[handle]/settings/account.tsx:343 +#~ msgid "The migration alias could not be removed. Please try again." +#~ msgstr "無法移除遷移別名。請再試一次。" + #: src/components/AppealDialog.tsx:103 msgid "The moderation team will review your appeal and notify you." msgstr "管理團隊將審核你的申訴並通知你。" @@ -4148,6 +4295,15 @@ msgstr "您要找的頁面不存在或已移動。" msgid "The passkey has been successfully revoked." msgstr "通行金鑰已成功撤銷。" +#: src/routes/(root)/[handle]/settings/account.tsx:294 +msgid "The previous account could not be added. Please try again." +msgstr "無法新增舊帳戶。請再試一次。" + +#: src/routes/(root)/[handle]/settings/account.tsx:337 +#: src/routes/(root)/[handle]/settings/account.tsx:345 +msgid "The previous account could not be removed. Please try again." +msgstr "無法移除舊帳戶。請再試一次。" + #: src/components/article-composer/ArticleComposerPublishFields.tsx:60 msgid "The primary language of your article, used for accessibility and discovery." msgstr "文章的主要語言,用於無障礙功能和內容發現。" @@ -4167,7 +4323,7 @@ msgstr "註冊連結無效。請確保你使用的是你收到的正確郵件連 #. placeholder {0}: "GITHUB_REPOSITORY" #. placeholder {1}: "AGPL-3.0" -#: src/components/AppSidebar.tsx:903 +#: src/components/AppSidebar.tsx:886 msgid "The source code of this website is available on {0} under the {1} license." msgstr "可在 {0} 上以 {1} 授權取得該網站的原始碼。" @@ -4192,7 +4348,7 @@ msgstr "Web Push 公開金鑰無效。" msgid "There are no moderation actions on your account." msgstr "你的帳戶沒有任何審核處理。" -#: src/routes/(root)/[handle]/settings/account.tsx:176 +#: src/routes/(root)/[handle]/settings/account.tsx:494 msgid "This account cannot be deleted right now. Please contact the instance administrators." msgstr "目前無法刪除此帳戶。請聯絡站台管理員。" @@ -4212,7 +4368,7 @@ msgstr "此帳戶已被停權。" msgid "This action cannot be undone. This will permanently delete this post." msgstr "此操作無法復原。這將永久刪除該內容。" -#: src/routes/(root)/[handle]/settings/account.tsx:223 +#: src/routes/(root)/[handle]/settings/account.tsx:541 msgid "This action is permanent." msgstr "此操作無法復原。" @@ -4221,7 +4377,7 @@ msgstr "此操作無法復原。" msgid "This browser does not support Web Push." msgstr "此瀏覽器不支援 Web Push。" -#: src/routes/(root)/[handle]/settings/account.tsx:264 +#: src/routes/(root)/[handle]/settings/account.tsx:583 msgid "This cannot be undone. Your account will be deleted and you will be signed out." msgstr "此操作無法復原。你的帳戶將被刪除,並且你會被登出。" @@ -4264,6 +4420,10 @@ msgstr "這是沒有本地通知或申訴的遠端行為者。警告僅作記錄 msgid "This is too long (maximum {MAX_REASON_LENGTH} characters)." msgstr "內容過長(最多 {MAX_REASON_LENGTH} 個字元)。" +#: src/routes/(root)/[handle]/settings/account.tsx:356 +msgid "This page only prepares the Hackers' Pub side of the move. The move still starts from your old server." +msgstr "此頁面只準備 Hackers' Pub 這邊的遷移。遷移仍需從舊伺服器開始。" + #: src/components/QuoteTargetPlaceholder.tsx:36 msgid "This post quoted another post, but the quote is not currently authorized." msgstr "此內容引用了另一則內容,但目前未獲得引用授權。" @@ -4308,7 +4468,7 @@ msgstr "通常需要一分鐘左右。翻譯完成後頁面將自動更新。" msgid "This will be part of the article URL." msgstr "這將成為文章網址的一部分。" -#: src/components/AppSidebar.tsx:167 +#: src/components/AppSidebar.tsx:150 msgid "Timeline" msgstr "時間軸" @@ -4357,9 +4517,9 @@ msgstr "正在翻譯為{name}…" msgid "Translating…" msgstr "正在翻譯…" -#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:379 -#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:402 -#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:411 +#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:391 +#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:414 +#: src/routes/(root)/[handle]/[idOrYear]/[slug]/[lang].tsx:423 #: src/routes/(root)/[handle]/[idOrYear]/[slug]/index.tsx:615 msgid "Translation request failed" msgstr "翻譯請求失敗" @@ -4383,7 +4543,7 @@ msgid "Try again" msgstr "重試" #. placeholder {0}: props.username -#: src/routes/(root)/[handle]/settings/account.tsx:241 +#: src/routes/(root)/[handle]/settings/account.tsx:560 msgid "Type {0} to confirm account deletion." msgstr "請輸入{0}以確認帳戶刪除。" @@ -4472,10 +4632,14 @@ msgstr "URL" msgid "URL pattern" msgstr "URL 模式" -#: src/components/AppSidebar.tsx:504 +#: src/components/AppSidebar.tsx:487 msgid "Use old UI" msgstr "使用舊版介面" +#: src/routes/(root)/[handle]/settings/account.tsx:375 +#~ msgid "Use the old account's handle or actor URL." +#~ msgstr "使用舊帳戶的識別碼或 actor URL。" + #: src/components/ProfileActionMenu.tsx:320 msgid "User blocked" msgstr "已封鎖使用者" @@ -4498,7 +4662,7 @@ msgstr "已解除封鎖使用者" msgid "User unmuted" msgstr "已解除靜音使用者" -#: src/routes/(root)/[handle]/settings/account.tsx:234 +#: src/routes/(root)/[handle]/settings/account.tsx:552 #: src/routes/(root)/[handle]/settings/index.tsx:423 #: src/routes/(root)/sign/up/[token].tsx:331 msgid "Username" @@ -4538,7 +4702,7 @@ msgstr "已於{1}驗證此連結歸{0}所有" msgid "Verifying your invitation…" msgstr "驗證您的邀請…" -#: src/components/AppSidebar.tsx:814 +#: src/components/AppSidebar.tsx:797 msgid "View all drafts →" msgstr "查看所有草稿 →" @@ -4677,7 +4841,7 @@ msgstr "撤銷決定" msgid "Withdrawn" msgstr "已撤銷" -#: src/components/AppSidebar.tsx:263 +#: src/components/AppSidebar.tsx:246 msgid "Without shares" msgstr "不含轉貼" @@ -4740,7 +4904,12 @@ msgstr "最多可附加 {MAX_MEDIA} 張圖片" msgid "You can change it only once, and the old username will become available to others." msgstr "你只能更改一次使用者名稱,而舊的使用者名稱會公開為別人使用。" -#: src/routes/(root)/[handle]/settings/account.tsx:192 +#: src/routes/(root)/[handle]/settings/account.tsx:280 +#: src/routes/(root)/[handle]/settings/account.tsx:329 +#~ msgid "You can change migration aliases only for your own account." +#~ msgstr "你只能變更自己帳戶的遷移別名。" + +#: src/routes/(root)/[handle]/settings/account.tsx:510 msgid "You can delete only your own account." msgstr "你只能刪除自己的帳戶。" @@ -4769,6 +4938,11 @@ msgstr "您只能檢視自己的收藏" msgid "You can only view your own drafts" msgstr "您只能檢視自己的草稿" +#: src/routes/(root)/[handle]/settings/account.tsx:280 +#: src/routes/(root)/[handle]/settings/account.tsx:331 +msgid "You can prepare migration only for your own account." +msgstr "你只能為自己的帳戶準備遷移。" + #: src/routes/(root)/[handle]/settings/passkeys.tsx:405 msgid "You don't have any passkeys registered yet." msgstr "您尚未註冊任何通行金鑰。" @@ -4856,6 +5030,14 @@ msgstr "你被邀請加入 Hackers' Pub" msgid "Your account is suspended, so you can't post right now. See your sanctions for details and how to appeal." msgstr "你的帳戶已被停權,目前無法發文。詳情及申訴方法請查看處置紀錄。" +#: src/routes/(root)/[handle]/settings/account.tsx:266 +#~ msgid "Your actor document now includes the previous account." +#~ msgstr "你的 actor 文件現在包含以前的帳戶。" + +#: src/routes/(root)/[handle]/settings/account.tsx:315 +#~ msgid "Your actor document was updated." +#~ msgstr "你的 actor 文件已更新。" + #: src/components/ModerationNotificationList.tsx:119 msgid "Your appeal was reviewed." msgstr "你的申訴已審核。" @@ -4909,7 +5091,7 @@ msgstr "您的偏好語言已更新。" msgid "Your profile settings have been updated successfully." msgstr "個人資料設定已成功更新。" -#: src/routes/(root)/[handle]/settings/account.tsx:226 +#: src/routes/(root)/[handle]/settings/account.tsx:544 msgid "Your profile, posts, drafts, follows, settings, and login credentials will be removed. Your current username will remain reserved." msgstr "你的個人檔案、內容、草稿、關注關係、設定和登入憑證將被移除。目前的使用者名稱將繼續保留。" diff --git a/web-next/src/routes/(root)/[handle]/settings/account.tsx b/web-next/src/routes/(root)/[handle]/settings/account.tsx index 60fa609c0..a4fde4350 100644 --- a/web-next/src/routes/(root)/[handle]/settings/account.tsx +++ b/web-next/src/routes/(root)/[handle]/settings/account.tsx @@ -1,10 +1,13 @@ import { type RouteDefinition, useParams } from "@solidjs/router"; import { graphql } from "relay-runtime"; -import { createMemo, createSignal, Show } from "solid-js"; +import { createMemo, createSignal, For, Show } from "solid-js"; import { createMutation, loadQuery, useRelayEnvironment } from "solid-relay"; +import IconPlus from "~icons/lucide/plus"; import IconTrash2 from "~icons/lucide/trash-2"; -import { SettingsCardPage } from "~/components/SettingsCardPage.tsx"; +import { SettingsContainer } from "~/components/SettingsContainer.tsx"; import { SettingsOwnerGuard } from "~/components/SettingsOwnerGuard.tsx"; +import { SettingsTabs } from "~/components/SettingsTabs.tsx"; +import { Title } from "~/components/Title.tsx"; import { AlertDialog, AlertDialogClose, @@ -15,9 +18,17 @@ import { AlertDialogTitle, } from "~/components/ui/alert-dialog.tsx"; import { Button } from "~/components/ui/button.tsx"; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "~/components/ui/card.tsx"; import { TextField, TextFieldDescription, + TextFieldErrorMessage, TextFieldInput, TextFieldLabel, } from "~/components/ui/text-field.tsx"; @@ -29,8 +40,10 @@ import { } from "~/lib/relayPreload.ts"; import { decodeRouteParam } from "~/lib/routeParam.ts"; import { removeSessionCookie } from "~/lib/sessionActions.ts"; +import type { accountAddMigrationAliasMutation } from "./__generated__/accountAddMigrationAliasMutation.graphql.ts"; import type { accountDeleteMutation } from "./__generated__/accountDeleteMutation.graphql.ts"; import type { accountPageQuery } from "./__generated__/accountPageQuery.graphql.ts"; +import type { accountRemoveMigrationAliasMutation } from "./__generated__/accountRemoveMigrationAliasMutation.graphql.ts"; export const route = { matchFilters: { @@ -46,6 +59,9 @@ const accountPageQuery = graphql` accountByUsername(username: $username) { id username + actor { + aliases + } ...SettingsTabs_account } } @@ -86,6 +102,62 @@ const accountDeleteMutation = graphql` } `; +const accountAddMigrationAliasMutation = graphql` + mutation accountAddMigrationAliasMutation($accountId: ID!, $actor: String!) { + addAccountMigrationAlias( + input: { accountId: $accountId, actor: $actor } + ) { + __typename + ... on AddAccountMigrationAliasPayload { + account { + id + actor { + id + aliases + } + } + } + ... on NotAuthenticatedError { + notAuthenticated + } + ... on NotAuthorizedError { + notAuthorized + } + ... on InvalidInputError { + inputPath + } + } + } +`; + +const accountRemoveMigrationAliasMutation = graphql` + mutation accountRemoveMigrationAliasMutation($accountId: ID!, $alias: URL!) { + removeAccountMigrationAlias( + input: { accountId: $accountId, alias: $alias } + ) { + __typename + ... on RemoveAccountMigrationAliasPayload { + account { + id + actor { + id + aliases + } + } + } + ... on NotAuthenticatedError { + notAuthenticated + } + ... on NotAuthorizedError { + notAuthorized + } + ... on InvalidInputError { + inputPath + } + } + } +`; + export default function AccountSettingsPage() { const params = useParams(); const { t } = useLingui(); @@ -103,18 +175,43 @@ export default function AccountSettingsPage() { > {(account) => ( - - - + <> + {t`Account settings`} + +

{t`Account settings`}

+ +
+ + + {t`Account migration`} + + {t`Prepare this account as the destination for a Mastodon-style move.`} + + + + + + + + + {t`Delete account`} + + {t`Permanently delete your account and sign out of this session.`} + + + + + + +
+
+ )}
@@ -123,6 +220,232 @@ export default function AccountSettingsPage() { ); } +interface AccountMigrationAliasesFormProps { + aliases: readonly string[]; + id: string; +} + +function AccountMigrationAliasesForm( + props: AccountMigrationAliasesFormProps, +) { + const { t } = useLingui(); + const [actor, setActor] = createSignal(""); + const [error, setError] = createSignal(""); + const [adding, setAdding] = createSignal(false); + const [removingAlias, setRemovingAlias] = createSignal(null); + const canAdd = createMemo(() => actor().trim() !== "" && !adding()); + const [addAlias] = createMutation( + accountAddMigrationAliasMutation, + ); + const [removeAliasMutation] = createMutation< + accountRemoveMigrationAliasMutation + >(accountRemoveMigrationAliasMutation); + + function showMutationError(title: string, description: string) { + showToast({ title, description, variant: "error" }); + } + + function onAdd(event: SubmitEvent) { + event.preventDefault(); + if (!canAdd()) return; + const value = actor().trim(); + setError(""); + setAdding(true); + addAlias({ + variables: { + accountId: props.id, + actor: value, + }, + onCompleted(response) { + setAdding(false); + const result = response.addAccountMigrationAlias; + if (result?.__typename === "AddAccountMigrationAliasPayload") { + setActor(""); + showToast({ + title: t`Previous account added`, + description: + t`Hackers' Pub now publishes the old account as another account that belongs to you.`, + }); + return; + } + if (result?.__typename === "NotAuthenticatedError") { + showMutationError( + t`Sign in required`, + t`Please sign in again before changing account migration settings.`, + ); + return; + } + if (result?.__typename === "NotAuthorizedError") { + showMutationError( + t`Cannot update this account`, + t`You can prepare migration only for your own account.`, + ); + return; + } + const message = + t`Enter the account you are moving from, such as @old@example.com or its actor URL.`; + setError(message); + showMutationError(t`Could not add previous account`, message); + }, + onError(error) { + console.error(error); + setAdding(false); + showMutationError( + t`Could not add previous account`, + t`The previous account could not be added. Please try again.` + + (import.meta.env.DEV ? `\n\n${error.message}` : ""), + ); + }, + }); + } + + function onRemove(alias: string) { + if (removingAlias() != null) return; + setError(""); + setRemovingAlias(alias); + removeAliasMutation({ + variables: { + accountId: props.id, + alias, + }, + onCompleted(response) { + setRemovingAlias(null); + const result = response.removeAccountMigrationAlias; + if (result?.__typename === "RemoveAccountMigrationAliasPayload") { + showToast({ + title: t`Previous account removed`, + description: + t`Hackers' Pub no longer publishes that account as another account that belongs to you.`, + }); + return; + } + if (result?.__typename === "NotAuthenticatedError") { + showMutationError( + t`Sign in required`, + t`Please sign in again before changing account migration settings.`, + ); + return; + } + if (result?.__typename === "NotAuthorizedError") { + showMutationError( + t`Cannot update this account`, + t`You can prepare migration only for your own account.`, + ); + return; + } + showMutationError( + t`Could not remove previous account`, + t`The previous account could not be removed. Please try again.`, + ); + }, + onError(error) { + console.error(error); + setRemovingAlias(null); + showMutationError( + t`Could not remove previous account`, + t`The previous account could not be removed. Please try again.` + + (import.meta.env.DEV ? `\n\n${error.message}` : ""), + ); + }, + }); + } + + return ( +
+
+

+ {t`This page only prepares the Hackers' Pub side of the move. The move still starts from your old server.`} +

+
    +
  1. + {t`Add the old account here. Hackers' Pub will publish it as another account that belongs to you.`} +
  2. +
  3. + {t`On the old server, open account migration settings and set this Hackers' Pub account as the new account.`} +
  4. +
  5. + {t`After the old server confirms the destination, it sends the Move activity and compatible servers can move followers here.`} +
  6. +
+
+ +
+
+ { + setActor(value); + if (error() !== "") setError(""); + }} + validationState={error() === "" ? "valid" : "invalid"} + > + {t`Old account`} + + + {t`Enter the account you are moving from, for example @old@example.com.`} + + } + > + {error()} + + + +
+
+ + 0} + fallback={ +

+ {t`No previous accounts added yet.`} +

+ } + > +
+ + {(alias) => ( +
+ + {alias} + + +
+ )} +
+
+
+
+ ); +} + interface AccountDeletionFormProps { id: string; username: string;