diff options
21 files changed, 448 insertions, 33 deletions
| diff --git a/changelog.d/post-languages.add b/changelog.d/post-languages.add new file mode 100644 index 000000000..04b350f3f --- /dev/null +++ b/changelog.d/post-languages.add @@ -0,0 +1 @@ +Allow to specify post language
\ No newline at end of file diff --git a/lib/pleroma/constants.ex b/lib/pleroma/constants.ex index 2828c79a9..2d08cd7a1 100644 --- a/lib/pleroma/constants.ex +++ b/lib/pleroma/constants.ex @@ -20,7 +20,8 @@ defmodule Pleroma.Constants do        "deleted_activity_id",        "pleroma_internal",        "generator", -      "rules" +      "rules", +      "language"      ]    ) @@ -39,7 +40,8 @@ defmodule Pleroma.Constants do        "summary",        "sensitive",        "attachment", -      "generator" +      "generator", +      "language"      ]    ) diff --git a/lib/pleroma/ecto_type/activity_pub/object_validators/content_language_map.ex b/lib/pleroma/ecto_type/activity_pub/object_validators/content_language_map.ex new file mode 100644 index 000000000..dcdab19f8 --- /dev/null +++ b/lib/pleroma/ecto_type/activity_pub/object_validators/content_language_map.ex @@ -0,0 +1,49 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.ContentLanguageMap do +  use Ecto.Type + +  import Pleroma.EctoType.ActivityPub.ObjectValidators.LanguageCode, +    only: [good_locale_code?: 1] + +  def type, do: :map + +  def cast(%{} = object) do +    with {status, %{} = data} when status in [:modified, :ok] <- validate_map(object) do +      {:ok, data} +    else +      {_, nil} -> {:ok, nil} +      {:error, _} -> :error +    end +  end + +  def cast(_), do: :error + +  def dump(data), do: {:ok, data} + +  def load(data), do: {:ok, data} + +  defp validate_map(%{} = object) do +    {status, data} = +      object +      |> Enum.reduce({:ok, %{}}, fn +        {lang, value}, {status, acc} when is_binary(lang) and is_binary(value) -> +          if good_locale_code?(lang) do +            {status, Map.put(acc, lang, value)} +          else +            {:modified, acc} +          end + +        _, {_status, acc} -> +          {:modified, acc} +      end) + +    if data == %{} do +      {status, nil} +    else +      {status, data} +    end +  end +end diff --git a/lib/pleroma/ecto_type/activity_pub/object_validators/language_code.ex b/lib/pleroma/ecto_type/activity_pub/object_validators/language_code.ex new file mode 100644 index 000000000..4779deeb0 --- /dev/null +++ b/lib/pleroma/ecto_type/activity_pub/object_validators/language_code.ex @@ -0,0 +1,27 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.LanguageCode do +  use Ecto.Type + +  def type, do: :string + +  def cast(language) when is_binary(language) do +    if good_locale_code?(language) do +      {:ok, language} +    else +      {:error, :invalid_language} +    end +  end + +  def cast(_), do: :error + +  def dump(data), do: {:ok, data} + +  def load(data), do: {:ok, data} + +  def good_locale_code?(code) when is_binary(code), do: code =~ ~r<^[a-zA-Z0-9\-]+\z$> + +  def good_locale_code?(_code), do: false +end diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex index c509890f6..ee12f3ebf 100644 --- a/lib/pleroma/web/activity_pub/object_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validator.ex @@ -26,6 +26,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do    alias Pleroma.Web.ActivityPub.ObjectValidators.AudioImageVideoValidator    alias Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator    alias Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator +  alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes    alias Pleroma.Web.ActivityPub.ObjectValidators.CreateChatMessageValidator    alias Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator    alias Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator @@ -115,7 +116,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do          meta        )        when objtype in ~w[Question Answer Audio Video Image Event Article Note Page] do -    with {:ok, object_data} <- cast_and_apply_and_stringify_with_history(object), +    with {:ok, object_data} <- +           object +           |> CommonFixes.maybe_add_language_from_activity(create_activity) +           |> cast_and_apply_and_stringify_with_history(),           meta = Keyword.put(meta, :object_data, object_data),           {:ok, create_activity} <-             create_activity @@ -165,7 +169,11 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do        )        when objtype in ~w[Question Answer Audio Video Event Article Note Page] do      with {_, false} <- {:local, Access.get(meta, :local, false)}, -         {_, {:ok, object_data, _}} <- {:object_validation, validate(object, meta)}, +         {_, {:ok, object_data, _}} <- +           {:object_validation, +            object +            |> CommonFixes.maybe_add_language_from_activity(update_activity) +            |> validate(meta)},           meta = Keyword.put(meta, :object_data, object_data),           {:ok, update_activity} <-             update_activity diff --git a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex index ada1a4ea9..81ab354fe 100644 --- a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex @@ -30,7 +30,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do    def cast_and_apply(data) do      data -    |> cast_data +    |> cast_data()      |> apply_action(:insert)    end @@ -88,6 +88,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do      |> CommonFixes.fix_likes()      |> Transmogrifier.fix_emoji()      |> Transmogrifier.fix_content_map() +    |> CommonFixes.maybe_add_language() +    |> CommonFixes.maybe_add_content_map()    end    def changeset(struct, data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fields.ex b/lib/pleroma/web/activity_pub/object_validators/common_fields.ex index 1a5d02601..22cf0cc05 100644 --- a/lib/pleroma/web/activity_pub/object_validators/common_fields.ex +++ b/lib/pleroma/web/activity_pub/object_validators/common_fields.ex @@ -31,6 +31,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFields do    defmacro object_fields do      quote bind_quoted: binding() do        field(:content, :string) +      field(:contentMap, ObjectValidators.ContentLanguageMap)        field(:published, ObjectValidators.DateTime)        field(:updated, ObjectValidators.DateTime) @@ -58,6 +59,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFields do        field(:like_count, :integer, default: 0)        field(:announcement_count, :integer, default: 0)        field(:quotes_count, :integer, default: 0) +      field(:language, ObjectValidators.LanguageCode)        field(:inReplyTo, ObjectValidators.ObjectID)        field(:quoteUrl, ObjectValidators.ObjectID)        field(:url, ObjectValidators.BareUri) diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex index a39110e10..87d3e0c8f 100644 --- a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex +++ b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex @@ -11,6 +11,11 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do    alias Pleroma.Web.ActivityPub.Transmogrifier    alias Pleroma.Web.ActivityPub.Utils +  import Pleroma.EctoType.ActivityPub.ObjectValidators.LanguageCode, +    only: [good_locale_code?: 1] + +  import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1] +    require Pleroma.Constants    def cast_and_filter_recipients(message, field, follower_collection, field_fallback \\ []) do @@ -132,4 +137,60 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do    end    def object_link_tag?(_), do: false + +  def maybe_add_language_from_activity(object, activity) do +    language = get_language_from_context(activity) + +    if language do +      Map.put(object, "language", language) +    else +      object +    end +  end + +  def maybe_add_language(object) do +    language = +      [ +        get_language_from_context(object), +        get_language_from_content_map(object) +      ] +      |> Enum.find(&good_locale_code?(&1)) + +    if language do +      Map.put(object, "language", language) +    else +      object +    end +  end + +  defp get_language_from_context(%{"@context" => context}) when is_list(context) do +    case context +         |> Enum.find(fn +           %{"@language" => language} -> language != "und" +           _ -> nil +         end) do +      %{"@language" => language} -> language +      _ -> nil +    end +  end + +  defp get_language_from_context(_), do: nil + +  defp get_language_from_content_map(%{"contentMap" => content_map, "content" => source_content}) do +    content_groups = Map.to_list(content_map) + +    case Enum.find(content_groups, fn {_, content} -> content == source_content end) do +      {language, _} -> language +      _ -> nil +    end +  end + +  defp get_language_from_content_map(_), do: nil + +  def maybe_add_content_map(%{"language" => language, "content" => content} = object) +      when not_empty_string(language) do +    Map.put(object, "contentMap", Map.put(%{}, language, content)) +  end + +  def maybe_add_content_map(object), do: object  end diff --git a/lib/pleroma/web/activity_pub/object_validators/event_validator.ex b/lib/pleroma/web/activity_pub/object_validators/event_validator.ex index c87515e80..ea14d6aca 100644 --- a/lib/pleroma/web/activity_pub/object_validators/event_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/event_validator.ex @@ -28,7 +28,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EventValidator do    def cast_and_apply(data) do      data -    |> cast_data +    |> cast_data()      |> apply_action(:insert)    end @@ -38,6 +38,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EventValidator do      |> validate_data()    end +  @spec cast_data(map()) :: map()    def cast_data(data) do      %__MODULE__{}      |> changeset(data) @@ -49,6 +50,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EventValidator do      |> CommonFixes.fix_object_defaults()      |> CommonFixes.fix_likes()      |> Transmogrifier.fix_emoji() +    |> CommonFixes.maybe_add_language() +    |> CommonFixes.maybe_add_content_map()    end    def changeset(struct, data) do diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 2f8a7f8f2..a6f711733 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -22,6 +22,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do    alias Pleroma.Web.Federator    import Ecto.Query +  import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1]    require Pleroma.Constants @@ -336,6 +337,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do    def fix_tag(object), do: object +  # prefer content over contentMap +  def fix_content_map(%{"content" => content} = object) when not_empty_string(content), do: object +    # content map usually only has one language so this will do for now.    def fix_content_map(%{"contentMap" => content_map} = object) do      content_groups = Map.to_list(content_map) @@ -750,12 +754,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do        object_id        |> Object.normalize(fetch: false)        |> Map.get(:data) -      |> prepare_object      data =        data -      |> Map.put("object", object) -      |> Map.merge(Utils.make_json_ld_header()) +      |> Map.put("object", prepare_object(object)) +      |> Map.merge(Utils.make_json_ld_header(object))        |> Map.delete("bcc")      {:ok, data} @@ -763,14 +766,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do    def prepare_outgoing(%{"type" => "Update", "object" => %{"type" => objtype} = object} = data)        when objtype in Pleroma.Constants.updatable_object_types() do -    object = -      object -      |> prepare_object -      data =        data -      |> Map.put("object", object) -      |> Map.merge(Utils.make_json_ld_header()) +      |> Map.put("object", prepare_object(object)) +      |> Map.merge(Utils.make_json_ld_header(object))        |> Map.delete("bcc")      {:ok, data} @@ -840,7 +839,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do        data        |> strip_internal_fields        |> maybe_fix_object_url -      |> Map.merge(Utils.make_json_ld_header()) +      |> Map.merge(Utils.make_json_ld_header(data))      {:ok, data}    end diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 6c792804d..f30c92abf 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -20,6 +20,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do    alias Pleroma.Web.Router.Helpers    import Ecto.Query +  import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1]    require Logger    require Pleroma.Constants @@ -109,18 +110,24 @@ defmodule Pleroma.Web.ActivityPub.Utils do      end    end -  def make_json_ld_header do +  def make_json_ld_header(data \\ %{}) do      %{        "@context" => [          "https://www.w3.org/ns/activitystreams",          "#{Endpoint.url()}/schemas/litepub-0.1.jsonld",          %{ -          "@language" => "und" +          "@language" => get_language(data)          }        ]      }    end +  defp get_language(%{"language" => language}) when not_empty_string(language) do +    language +  end + +  defp get_language(_), do: "und" +    def make_date do      DateTime.utc_now() |> DateTime.to_iso8601()    end diff --git a/lib/pleroma/web/activity_pub/views/object_view.ex b/lib/pleroma/web/activity_pub/views/object_view.ex index 63caa915c..13b5b2542 100644 --- a/lib/pleroma/web/activity_pub/views/object_view.ex +++ b/lib/pleroma/web/activity_pub/views/object_view.ex @@ -9,7 +9,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectView do    alias Pleroma.Web.ActivityPub.Transmogrifier    def render("object.json", %{object: %Object{} = object}) do -    base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header() +    base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header(object.data)      additional = Transmogrifier.prepare_object(object.data)      Map.merge(base, additional) @@ -17,7 +17,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectView do    def render("object.json", %{object: %Activity{data: %{"type" => activity_type}} = activity})        when activity_type in ["Create", "Listen"] do -    base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header() +    base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header(activity.data)      object = Object.normalize(activity, fetch: false)      additional = @@ -28,7 +28,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectView do    end    def render("object.json", %{object: %Activity{} = activity}) do -    base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header() +    base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header(activity.data)      object_id = Object.normalize(activity, id_only: true)      additional = diff --git a/lib/pleroma/web/common_api/activity_draft.ex b/lib/pleroma/web/common_api/activity_draft.ex index 8aa1e258d..4220757df 100644 --- a/lib/pleroma/web/common_api/activity_draft.ex +++ b/lib/pleroma/web/common_api/activity_draft.ex @@ -11,6 +11,9 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do    alias Pleroma.Web.CommonAPI    alias Pleroma.Web.CommonAPI.Utils +  import Pleroma.EctoType.ActivityPub.ObjectValidators.LanguageCode, +    only: [good_locale_code?: 1] +    import Pleroma.Web.Gettext    import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1] @@ -38,6 +41,7 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do              cc: [],              context: nil,              sensitive: false, +            language: nil,              object: nil,              preview?: false,              changes: %{} @@ -64,6 +68,7 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do      |> content()      |> with_valid(&to_and_cc/1)      |> with_valid(&context/1) +    |> with_valid(&language/1)      |> sensitive()      |> with_valid(&object/1)      |> preview?() @@ -249,6 +254,16 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do      %__MODULE__{draft | sensitive: sensitive}    end +  defp language(draft) do +    language = draft.params[:language] + +    if good_locale_code?(language) do +      %__MODULE__{draft | language: language} +    else +      draft +    end +  end +    defp object(draft) do      emoji = Map.merge(Pleroma.Emoji.Formatter.get_emoji_map(draft.full_payload), draft.emoji) @@ -288,6 +303,7 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do          "mediaType" => Utils.get_content_type(draft.params[:content_type])        })        |> Map.put("generator", draft.params[:generator]) +      |> Map.put("language", draft.language)      %__MODULE__{draft | object: object}    end diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index 3bf870c24..10966edd6 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -227,7 +227,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do        mentions: mentions,        tags: reblogged[:tags] || [],        application: build_application(object.data["generator"]), -      language: nil, +      language: get_language(object),        emojis: [],        pleroma: %{          local: activity.local, @@ -445,7 +445,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do        mentions: mentions,        tags: build_tags(tags),        application: build_application(object.data["generator"]), -      language: nil, +      language: get_language(object),        emojis: build_emojis(object.data["emoji"]),        pleroma: %{          local: activity.local, @@ -829,6 +829,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do      Utils.get_content_type(nil)    end +  defp get_language(%{data: %{"language" => "und"}}), do: nil + +  defp get_language(object), do: object.data["language"] +    defp proxied_url(url, page_url_data) do      if is_binary(url) do        build_image_url(URI.parse(url), page_url_data) |> MediaProxy.url() diff --git a/test/pleroma/ecto_type/activity_pub/object_validators/content_language_map_test.exs b/test/pleroma/ecto_type/activity_pub/object_validators/content_language_map_test.exs new file mode 100644 index 000000000..a05871a6f --- /dev/null +++ b/test/pleroma/ecto_type/activity_pub/object_validators/content_language_map_test.exs @@ -0,0 +1,56 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.ContentLanguageMapTest do +  use Pleroma.DataCase, async: true + +  alias Pleroma.EctoType.ActivityPub.ObjectValidators.ContentLanguageMap + +  test "it validates" do +    data = %{ +      "en-US" => "mew mew", +      "en-GB" => "meow meow" +    } + +    assert {:ok, ^data} = ContentLanguageMap.cast(data) +  end + +  test "it validates empty strings" do +    data = %{ +      "en-US" => "mew mew", +      "en-GB" => "" +    } + +    assert {:ok, ^data} = ContentLanguageMap.cast(data) +  end + +  test "it ignores non-strings within the map" do +    data = %{ +      "en-US" => "mew mew", +      "en-GB" => 123 +    } + +    assert {:ok, validated_data} = ContentLanguageMap.cast(data) + +    assert validated_data == %{"en-US" => "mew mew"} +  end + +  test "it ignores bad locale codes" do +    data = %{ +      "en-US" => "mew mew", +      "en_GB" => "meow meow", +      "en<<#@!$#!@%!GB" => "meow meow" +    } + +    assert {:ok, validated_data} = ContentLanguageMap.cast(data) + +    assert validated_data == %{"en-US" => "mew mew"} +  end + +  test "it complains with non-map data" do +    assert :error = ContentLanguageMap.cast("mew") +    assert :error = ContentLanguageMap.cast(["mew"]) +    assert :error = ContentLanguageMap.cast([%{"en-US" => "mew"}]) +  end +end diff --git a/test/pleroma/ecto_type/activity_pub/object_validators/language_code_test.exs b/test/pleroma/ecto_type/activity_pub/object_validators/language_code_test.exs new file mode 100644 index 000000000..086bb3e97 --- /dev/null +++ b/test/pleroma/ecto_type/activity_pub/object_validators/language_code_test.exs @@ -0,0 +1,29 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.LanguageCodeTest do +  use Pleroma.DataCase, async: true + +  alias Pleroma.EctoType.ActivityPub.ObjectValidators.LanguageCode + +  test "it accepts language code" do +    text = "pl" +    assert {:ok, ^text} = LanguageCode.cast(text) +  end + +  test "it accepts language code with region" do +    text = "pl-PL" +    assert {:ok, ^text} = LanguageCode.cast(text) +  end + +  test "errors for invalid language code" do +    assert {:error, :invalid_language} = LanguageCode.cast("ru_RU") +    assert {:error, :invalid_language} = LanguageCode.cast(" ") +    assert {:error, :invalid_language} = LanguageCode.cast("en-US\n") +  end + +  test "errors for non-text" do +    assert :error == LanguageCode.cast(42) +  end +end diff --git a/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs b/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs index b1cbdbe81..829598246 100644 --- a/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs +++ b/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs @@ -187,4 +187,71 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest               name: "RE: https://server.example/objects/123"             }    end + +  describe "Note language" do +    test "it detects language from JSON-LD context" do +      user = insert(:user) + +      note_activity = %{ +        "@context" => ["https://www.w3.org/ns/activitystreams", %{"@language" => "pl"}], +        "to" => ["https://www.w3.org/ns/activitystreams#Public"], +        "cc" => [], +        "type" => "Create", +        "object" => %{ +          "to" => ["https://www.w3.org/ns/activitystreams#Public"], +          "cc" => [], +          "id" => Utils.generate_object_id(), +          "type" => "Note", +          "content" => "Szczęść Boże", +          "attributedTo" => user.ap_id +        }, +        "actor" => user.ap_id +      } + +      {:ok, _create_activity, meta} = ObjectValidator.validate(note_activity, []) + +      assert meta[:object_data]["language"] == "pl" +    end + +    test "it detects language from contentMap" do +      user = insert(:user) + +      note = %{ +        "to" => ["https://www.w3.org/ns/activitystreams#Public"], +        "cc" => [], +        "id" => Utils.generate_object_id(), +        "type" => "Note", +        "content" => "Szczęść Boże", +        "contentMap" => %{ +          "de" => "Gott segne", +          "pl" => "Szczęść Boże" +        }, +        "attributedTo" => user.ap_id +      } + +      {:ok, object} = ArticleNotePageValidator.cast_and_apply(note) + +      assert object.language == "pl" +    end + +    test "it adds contentMap if language is specified" do +      user = insert(:user) + +      note = %{ +        "to" => ["https://www.w3.org/ns/activitystreams#Public"], +        "cc" => [], +        "id" => Utils.generate_object_id(), +        "type" => "Note", +        "content" => "тест", +        "language" => "uk", +        "attributedTo" => user.ap_id +      } + +      {:ok, object} = ArticleNotePageValidator.cast_and_apply(note) + +      assert object.contentMap == %{ +               "uk" => "тест" +             } +    end +  end  end diff --git a/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs index ed71dcb90..fd7a3c772 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs @@ -219,6 +219,36 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do                 "<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span></p>"      end +    test "it only uses contentMap if content is not present" do +      user = insert(:user) + +      message = %{ +        "@context" => "https://www.w3.org/ns/activitystreams", +        "to" => ["https://www.w3.org/ns/activitystreams#Public"], +        "cc" => [], +        "type" => "Create", +        "object" => %{ +          "to" => ["https://www.w3.org/ns/activitystreams#Public"], +          "cc" => [], +          "id" => Utils.generate_object_id(), +          "type" => "Note", +          "content" => "Hi", +          "contentMap" => %{ +            "de" => "Hallo", +            "uk" => "Привіт" +          }, +          "inReplyTo" => nil, +          "attributedTo" => user.ap_id +        }, +        "actor" => user.ap_id +      } + +      {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(message) +      object = Object.normalize(data["object"], fetch: false) + +      assert object.data["content"] == "Hi" +    end +      test "it works for incoming notices with a nil contentMap (firefish)" do        data =          File.read!("test/fixtures/mastodon-post-activity-contentmap.json") diff --git a/test/pleroma/web/activity_pub/transmogrifier_test.exs b/test/pleroma/web/activity_pub/transmogrifier_test.exs index 6da7e4a89..ebf70b3e6 100644 --- a/test/pleroma/web/activity_pub/transmogrifier_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier_test.exs @@ -384,6 +384,24 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert modified["object"]["quoteUrl"] == quote_id        assert modified["object"]["quoteUri"] == quote_id      end + +    test "it adds language of the object to its json-ld context" do +      user = insert(:user) + +      {:ok, activity} = CommonAPI.post(user, %{status: "Cześć", language: "pl"}) +      {:ok, modified} = Transmogrifier.prepare_outgoing(activity.object.data) + +      assert [_, _, %{"@language" => "pl"}] = modified["@context"] +    end + +    test "it adds language of the object to Create activity json-ld context" do +      user = insert(:user) + +      {:ok, activity} = CommonAPI.post(user, %{status: "Cześć", language: "pl"}) +      {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data) + +      assert [_, _, %{"@language" => "pl"}] = modified["@context"] +    end    end    describe "actor rewriting" do diff --git a/test/pleroma/web/activity_pub/utils_test.exs b/test/pleroma/web/activity_pub/utils_test.exs index 872a440cb..45fef154e 100644 --- a/test/pleroma/web/activity_pub/utils_test.exs +++ b/test/pleroma/web/activity_pub/utils_test.exs @@ -173,16 +173,30 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do      end    end -  test "make_json_ld_header/0" do -    assert Utils.make_json_ld_header() == %{ -             "@context" => [ -               "https://www.w3.org/ns/activitystreams", -               "http://localhost:4001/schemas/litepub-0.1.jsonld", -               %{ -                 "@language" => "und" -               } -             ] -           } +  describe "make_json_ld_header/1" do +    test "makes jsonld header" do +      assert Utils.make_json_ld_header() == %{ +               "@context" => [ +                 "https://www.w3.org/ns/activitystreams", +                 "http://localhost:4001/schemas/litepub-0.1.jsonld", +                 %{ +                   "@language" => "und" +                 } +               ] +             } +    end + +    test "includes language if specified" do +      assert Utils.make_json_ld_header(%{"language" => "pl"}) == %{ +               "@context" => [ +                 "https://www.w3.org/ns/activitystreams", +                 "http://localhost:4001/schemas/litepub-0.1.jsonld", +                 %{ +                   "@language" => "pl" +                 } +               ] +             } +    end    end    describe "get_existing_votes" do diff --git a/test/pleroma/web/mastodon_api/views/status_view_test.exs b/test/pleroma/web/mastodon_api/views/status_view_test.exs index bc6dec32a..e6a164d72 100644 --- a/test/pleroma/web/mastodon_api/views/status_view_test.exs +++ b/test/pleroma/web/mastodon_api/views/status_view_test.exs @@ -951,6 +951,26 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do      assert status.edited_at    end +  test "it shows post language" do +    user = insert(:user) + +    {:ok, post} = CommonAPI.post(user, %{status: "Szczęść Boże", language: "pl"}) + +    status = StatusView.render("show.json", activity: post) + +    assert status.language == "pl" +  end + +  test "doesn't show post language if it's 'und'" do +    user = insert(:user) + +    {:ok, post} = CommonAPI.post(user, %{status: "sdifjogijodfg", language: "und"}) + +    status = StatusView.render("show.json", activity: post) + +    assert status.language == nil +  end +    test "with a source object" do      note =        insert(:note, | 
