diff --git a/tools/cldr-apps/js/src/esm/cldrAnnounce.mjs b/tools/cldr-apps/js/src/esm/cldrAnnounce.mjs
index d9515685457..056611e93aa 100644
--- a/tools/cldr-apps/js/src/esm/cldrAnnounce.mjs
+++ b/tools/cldr-apps/js/src/esm/cldrAnnounce.mjs
@@ -124,6 +124,9 @@ function canChooseAllOrgs() {
return cldrStatus.getPermissions()?.userIsTC || false;
}
+/**
+ * @param localeState 'ddl' or 'all' or 'choose'
+ */
async function compose(formState, viewCallbackComposeResult) {
resetSchedule();
const init = cldrAjax.makePostData(formState);
diff --git a/tools/cldr-apps/js/src/views/AnnounceForm.vue b/tools/cldr-apps/js/src/views/AnnounceForm.vue
index 2a49e0a0da8..c18dd5ab5ef 100644
--- a/tools/cldr-apps/js/src/views/AnnounceForm.vue
+++ b/tools/cldr-apps/js/src/views/AnnounceForm.vue
@@ -16,6 +16,9 @@
Mine
TC Orgs
+ Non-TC Orgs
All
@@ -40,11 +43,17 @@
-
+
+ All
+ All DDL (non-TC) Locales
+ Choose…
+
+
Cancel
- Post
@@ -83,7 +96,7 @@
diff --git a/tools/cldr-apps/src/main/java/org/unicode/cldr/web/AnnouncementData.java b/tools/cldr-apps/src/main/java/org/unicode/cldr/web/AnnouncementData.java
index 061a74b921b..1682fae02ab 100644
--- a/tools/cldr-apps/src/main/java/org/unicode/cldr/web/AnnouncementData.java
+++ b/tools/cldr-apps/src/main/java/org/unicode/cldr/web/AnnouncementData.java
@@ -2,10 +2,11 @@
import com.ibm.icu.dev.util.ElapsedTimer;
import java.sql.*;
-import java.sql.Timestamp;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
+import org.unicode.cldr.test.SubmissionLocales;
import org.unicode.cldr.util.*;
import org.unicode.cldr.web.api.Announcements;
@@ -148,6 +149,7 @@ private static void emailNotify(
}
String subject = "CLDR Survey Tool announcement: " + request.subject;
String locs = (request.locs == null || request.locs.isEmpty()) ? "All" : request.locs;
+ if (locs.equals(Announcements.LOCS_NON_TC)) locs = "(DDL Locales)";
String body =
"From: "
+ poster.name
@@ -223,7 +225,16 @@ private static void addRecipientIfPasses(
AnnouncementFilter aFilter = new AnnouncementFilter(user);
Announcements.Announcement a =
new Announcements.Announcement(0, poster.id, null, null, null);
- a.setFilters(request.locs, request.orgs, request.audience);
+ String filterLocs = request.locs;
+ if (filterLocs != null && filterLocs.equals(Announcements.LOCS_NON_TC)) {
+ // expand the filter
+ filterLocs =
+ SurveyMain.getLocalesSet().stream()
+ .filter(loc -> !SubmissionLocales.isTcLocale(loc))
+ .map(l -> l.getBaseName())
+ .collect(Collectors.joining(" "));
+ }
+ a.setFilters(filterLocs, request.orgs, request.audience);
if (aFilter.passes(a)) {
logger.fine("In AnnouncementData.addRecipientIfPasses, adding recipient: " + user.id);
recipients.add(user.id);
@@ -470,6 +481,8 @@ private boolean matchOrg(String orgs, int posterId) {
return true;
} else if (Announcements.ORGS_TC.equals(orgs)) {
return user.getOrganization().isTCOrg();
+ } else if (Announcements.ORGS_NON_TC.equals(orgs)) {
+ return !user.getOrganization().isTCOrg();
} else if (Announcements.ORGS_MINE.equals(orgs)) {
UserRegistry.User posterUser = CookieSession.sm.reg.getInfo(posterId);
return posterUser != null && posterUser.isSameOrg(user);
diff --git a/tools/cldr-apps/src/main/java/org/unicode/cldr/web/api/Announcements.java b/tools/cldr-apps/src/main/java/org/unicode/cldr/web/api/Announcements.java
index 1688aefb68e..a761da1d9f4 100644
--- a/tools/cldr-apps/src/main/java/org/unicode/cldr/web/api/Announcements.java
+++ b/tools/cldr-apps/src/main/java/org/unicode/cldr/web/api/Announcements.java
@@ -11,8 +11,10 @@
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
+import org.unicode.cldr.test.SubmissionLocales;
import org.unicode.cldr.util.LocaleNormalizer;
import org.unicode.cldr.util.LocaleSet;
+import org.unicode.cldr.util.Organization;
import org.unicode.cldr.web.*;
@ApplicationScoped
@@ -25,15 +27,26 @@ public class Announcements {
public static final String AUDIENCE_EVERYONE = "Everyone";
public static final String ORGS_MINE = "Mine";
+ /** all TC orgs, as defined by {@link Organization#isTCOrg()} */
public static final String ORGS_TC = "TC";
+ /** excluding TC orgs, as defined by {@link Organization#isTCOrg()} */
+ public static final String ORGS_NON_TC = "NonTC";
+ /** All organizations */
public static final String ORGS_ALL = "All";
+ /**
+ * Special value for ddl (non tc) locales. This special value for locales sends to all locales,
+ * but only those which are currently not defined as TC Locales by the SubmissionLocales class.
+ * {@link SubmissionLocales#isTcLocale(org.unicode.cldr.util.CLDRLocale)}
+ */
+ public static final String LOCS_NON_TC = "!";
+
private static final Set validAudiences =
new HashSet<>(
Arrays.asList(
AUDIENCE_TC, AUDIENCE_MANAGERS, AUDIENCE_VETTERS, AUDIENCE_EVERYONE));
private static final Set validOrgs =
- new HashSet<>(Arrays.asList(ORGS_MINE, ORGS_TC, ORGS_ALL));
+ new HashSet<>(Arrays.asList(ORGS_MINE, ORGS_NON_TC, ORGS_TC, ORGS_ALL));
@GET
@Produces(MediaType.APPLICATION_JSON)
@@ -242,6 +255,9 @@ public SubmissionRequest() {
@Schema(description = "locales")
public String locs = null;
+ @Schema(description = "localeType: one of 'all', 'ddl', or 'choose'", example = "choose")
+ public String localeType = null;
+
@Schema(description = "orgs")
public String orgs = null;
@@ -250,7 +266,14 @@ public boolean isValid() {
}
public void normalize() {
- if (locs != null) {
+ if ("ddl".equals(localeType)) {
+ // special value for ddl (non-tc) locales.
+ // "ddl" means non-tc locales.
+ locs = LOCS_NON_TC;
+ } else if ("all".equals(localeType)) {
+ // all locales
+ locs = null;
+ } else if (locs != null) {
String normalized = LocaleNormalizer.normalizeQuietly(locs);
LocaleSet locSet = LocaleNormalizer.setFromStringQuietly(normalized, null);
LocaleSet langSet = locSet.combineRegionalVariants();